登录  /  注册
博主信息
博文 82
粉丝 0
评论 1
访问量 125589
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
最短和为给定数值的连续子序列(还未解决)
子龙的博客搬家啦httpswwwcnblogscomZiLongZiLong
原创
1606人浏览过

题目描述:

返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K 。

如果没有和至少为 K 的非空子数组,返回 -1 。

我想了好几天,想出的解决方案,以及优化方案(不知道为什么,我只能想出暴力枚举的解法):

/**
 * @param {number[]} A
 * @param {number} K
 * @return {number}
 */
var shortestSubarray = function(A, K) {
    let result = {
        length: Infinity
    },
    sums = {},
        start = 0,l = A.length;
    
    function sum(start,end){
        if( !A[start] || !A[end] ) return {
            sum: 0,
            length:Infinity
        };//prevent Array bounds
        let sum = 0;
        if( sums[start+'$'+end] !== undefined ) return{
            sum: sum,
            length: end - start + 1
        }
        if( sums[ (start-1) + '$'+end ] !== undefined ){//往右看看 start-1 -- end 和求出来了没
            sums[start+'$'+end] = sums[ (start-1) + '$'+end ] - A[(start-1)];
            return{
                sum: sums[ (start-1) + '$'+end ] - A[(start-1)],
                length: end - start +1
            }
        }
        if( sums[ start + '$' + (end-1) ] !== undefined ){// 往左看看 start -- end-1的和求出来没
            sums[start+'$'+end] = sums[start + '$' + (end - 1)] + A[end];
            return{
                sum: sums[start + '$' + (end - 1)] + A[end],
                length: end - start +1
            }
            
        }    
        for(let i = start ; i <= end; i++ ){
            sum += A[i]
            // if( sum >= K )
            //     return {
            //         sum: sum,
            //         length: i - start + 1
            //     }
        }
        /** 
         * 今天决定优化一下性能,阿西吧;
         * 如果 start --- end 的和已经存在,
         * 那么 start + 1 --- end 的和应该等于 sum(start,end) - A[start]
         */
        sums[start + '$' + end] = sum;
        return  {
                    sum: sum,
                    length: end - start + 1
        };
    }
    
    for( let i = 0,l = A.length; i < l; i++ ){
        if( A[i] >= K ){
            return 1;
        }else{
            for( let k=i-1,j = i+1; j<l || k >= 0;j++,k-- ){// 双指针,以此寻找左右的子数组和
                let leftSum = (k >= 0) && sum( k , i),
                
                    rightSum = (j < l) && sum(i,j);
                if( leftSum.sum >= K  ){
                    if( leftSum.length < result.length ){
                        result.length  = leftSum.length;
                    }
                }
                if(rightSum.sum >= K){
                   if( rightSum.length < result.length ){
                        result.length  = rightSum.length;
                    }
                 }
            }//for
            
        }
    }
    
    
    if( result.length == Infinity ){
        return -1;
    }else{
        return result.length;
    }
    
    
};

谈一下自己的思路吧,就是遍历数组的每个元素,然后以每个元素为中心,向左,向右逐渐求出每段子序列的和,为了性能优化,我还特别的将每段数组的和以 他的start + ‘$’+ end, 为key,以他的和为value保存了下来,这样求一段元素的和只要看看他start-1 --- end,或  start --- end-1 求出来了没有,如果有,就直接采取一个加法操作,直接求和,然而 即使进行了优化,还是没有解决根本问题,从for循环开始,整个算法的复杂度至少达到了 n*n 级别,当然啦最后的结果就是超时。。。。。。

emmm,我又想起来昨天看到的上次的周赛的第一名japen coder的代码,全是二进制运算,我感觉我这辈子都写不出来这种代码了。

本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!
全部评论 文明上网理性发言,请遵守新闻评论服务协议
0条评论
作者最新博文
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号

  • 登录PHP中文网,和优秀的人一起学习!
    全站2000+教程免费学