在LeetCode刷算法题,记录一下一道比较难的题目和至少为 K 的最短子数组
问题描述
返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K 。
如果没有和至少为 K 的非空子数组,返回 -1 。
其中:
- 1 <= A.length <= 50000
- -10 ^ 5 <= A[i] <= 10 ^ 5
- 1 <= K <= 10 ^ 9
最先想到的是依照数值长度进行遍历,但时间复杂度为O(n^2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| * @param {number[]} A * @param {number} K * @return {number} */ const shortestSubarray = (A, K) => { let preSum = 0 let count = 1 while (count <= A.length) { preSum += A[count - 1] let sum = preSum if (sum >= K) return count for (let i = 1; i + count <= A.length; i ++) { sum = sum - A[i - 1] + A[i + count - 1] if (sum >= K) return count } count += 1 } return -1 }
|
之后参考了网上的资料,可以使用Sliding Window的方法,复杂度可以下降到O(N)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| * @param {number[]} A * @param {number} K * @return {number} */ const shortestSubarray = (A, K) => { if (!A.length) return -1 let S = [0] for (let i = 0; i < A.length; i++) { S[i + 1] = S[i] + A[i] } const queue = [] let ans = A.length + 1 for (let j = 0; j < A.length + 1; j++) { while (queue.length && S[j] <= S[queue[queue.length - 1]]) { queue.pop() } while(queue.length && S[j] >= S[queue[0]] + K) { ans = Math.min(ans, j - queue.shift()) } queue.push(j) } return ans < A.length + 1 ? ans : -1 }
|