題目描述:
返回a
的最短的非空連續子陣列的長度,該子陣列的和至少為k
。
如果沒有和至少為k
的非空子陣列,返回-1
示例:
輸入:a = [1], k = 1
輸出:1
輸入:a = [1,2], k = 4
輸出:-1
輸入:a = [2,-1,2], k = 3
輸出:3
1. 1 <= a.length <= 50000
2. -10 ^ 5 <= a[i] <= 10 ^ 5
3. 1 <= k <= 10 ^ 9
首先對於我這樣乙個不怎麼有基礎的人來說,這道題著實是令我作嘔。。解題也是通過了其它題解的啟發。下面就開始吧。
解題想法:
由於題目中已經明確表示了陣列的長度為50000,因此如果要使用暴力接法,勢必造成o(n^2)的時間複雜度。因此就要想辦法讓i, j兩個迴圈變數只跑一遍。而對於這道題因為繞不開要求取陣列中的區間和。所以可以採用的乙個方法是字首和思想。大致的意思就是sum[i] = array[0] + array[1] + … + array[i - 1]利用這個字首和陣列就可以較為方便的得到乙個陣列的區間和,例如要知道區間[1, 3]的和,我們可以利用字首和陣列得到sum[4] - sum[1](這裡需要注意的是,為了便於計算字首和陣列的第零個元素預設為零)
解決了字首和之後就要解決更加關鍵的問題,如何能夠得到最短長度的和最小序列。首先我們不妨先這麼想,如果我們當前的索引為i, 此時若區間[0, i]的和比區間[0, i - 1]的和要小,那麼就不需要再考慮i - 1這個位置的索引了(因為這個時候有sum[a.length] - sum[i] > sum[a.length] - sum[i - 1] 且前者的區間長度要小於後者)而這個時候就要原先的儲存的i - 1
這個索引彈出,再將更優的i
索引加入。這個時候可以利用佇列這樣的資料結構來儲存。有了這個存刪的機制就可以保證每次能夠得到的長度都是最短且和最大的。之後就是獲得長度的問題了。如果這個佇列中還有元素的話,就從當前遍歷到的索引i
的字首和減去佇列頭部儲存的索引,即(sum[i] - sum[queue.front()]
)這個條件需要滿足題目中給出的k。由此可以看出這個佇列需要兩端都能出,因此我們需要維護乙個單調遞增的雙端佇列。下面附上c++**
class
solution
for(
int i =
0; i < len +1;
++i)
// 從佇列頭部開始尋找滿足條件的最短區間
// 如果不滿足條件就要將佇列頭部元素刪除
while
(dque.
size()
&& sum[i]
- sum[dque.
front()
]>= threshold)
} dque.
push_back
(i);
}return minlength ==
5e4+11?
-1: minlength;}}
;
LeetCode 862 和至少為K的最短子陣列
leetcode 862 和至少為k的最短子陣列 題目大意 給你乙個整數陣列 nums 和乙個整數 k 找出 nums 中和至少為 k 的最短非空子陣列,並返回該子陣列的長度。如果不存在這樣的子陣列,返回 1 子陣列是陣列中連續的一部分。題解 由於陣列中可能出現負數,所以尺取法不可行,需要使用單調佇...
和至少為K的最短子陣列
返回 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 重點就是每次遍歷的時候,加到i的時候,把i之前的負數...
leetcode 和為k的子陣列
class solution public int subarraysum vector nums,int k if nums.size 0 return 0 int res 0 unordered mapmap map 0 1 int sum 0 for int i 0 i從j到i求和等於k,不斷...