Blogger Information
Blog 82
fans 0
comment 1
visits 107900
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
最短和为给定数值的连续子序列(还未解决)
子龙的博客搬家啦httpswwwcnblogscomZiLongZiLong
Original
1439 people have browsed it

题目描述:

返回 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的代码,全是二进制运算,我感觉我这辈子都写不出来这种代码了。

Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post