最短和为给定数值的连续子序列(还未解决)
题目描述:
返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K 。
如果没有和至少为 K 的非空子数组,返回 -1 。
我想了好几天,想出的解决方案,以及优化方案(不知道为什么,我只能想出暴力枚举的解法):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | /** * @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的代码,全是二进制运算,我感觉我这辈子都写不出来这种代码了。
本文作者:子龙的博客
本文链接:https://www.cnblogs.com/ZiLongZiLong/p/17144918.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步