leetcode 862. 和至少為K的最短子陣列
阿新 • • 發佈:2018-12-16
1 題目描述
返回 A 的最短的非空連續子陣列的長度,該子陣列的和至少為 K 。
如果沒有和至少為 K 的非空子陣列,返回 -1 。
示例 1:
輸入:A = [1], K = 1 輸出:1
示例 2:
輸入:A = [1,2], K = 4 輸出:-1
示例 3:
輸入:A = [2,-1,2], K = 3 輸出:3
提示:
1 <= A.length <= 50000 -10 ^ 5 <= A[i] <= 10 ^ 5 1 <= K <= 10 ^ 9
2 思路
我沒什麼思路,我好菜啊。我只能在O(N)時間內計算A的累積和陣列sums,這樣任意指定兩個位置都能計算他們之間所有數的和。我只想到了O(N^2)的複雜度的解法。
我在網上看了別人的解法,他們好厲害啊。
https://www.jianshu.com/p/f80e7bc7af7b
有一個雙端佇列deque,變數i從0開始到n(包含)遍歷,佇列中存放的是之間可能的開始位置,i為結束位置。如果deque[0]滿足條件(就是deuqe[0]開始,i結束的字陣列和至少為K),就刪除它,然後再迴圈判斷,直到deque[0]不滿足條件。deque中位置對應的值是從小到大的,0不滿足,後面更不可能滿足,所以不用再判斷。如果i比隊尾元素小或相等,就刪除隊尾,迴圈判斷,直到i比隊尾元素大。
import java.util.ArrayDeque; import java.util.Deque; class Solution { public int shortestSubarray(int[] A, int K) { int n = A.length; // A的累計和陣列,sums[i] = sums(A[0]+A[1]+...+A[i]) int[] sums = new int[n+1]; sums[0] = 0; for (int i = 1; i <= n; i++) { sums[i] = sums[i-1]+A[i-1]; } int minWindowSize = n+1; Deque<Integer> deque = new ArrayDeque<Integer>(); for (int i = 0; i <= n; i++) { while (!deque.isEmpty() && sums[i] - sums[deque.getFirst()] >= K) { minWindowSize = Integer.min(minWindowSize, i-deque.getFirst()); deque.removeFirst(); } while (!deque.isEmpty() && sums[i] <= sums[deque.getLast()]) { deque.removeLast(); } deque.add(i); } if (minWindowSize == n+1) return -1; return minWindowSize; } }