一、題目描述
給定一個含有 n 個正整數的數組和一個正整數 s ,找出該數組中滿足其和 ≥ s 的長度最小的連續子數組,並返回其長度。如果不存在符合條件的連續子數組,返回 0。
二、示例
三、思路分析
這個題目我們拿到之後分析,他要一個連續的區間,是一個典型的雙指針問題,我們使用快慢指針以及兩層循環實現。
連續子數組可以表示爲 [i,j]:從第 i 項到第 j 項
如果 [i,j] 的 sum >= s ,如果擴張窗口,條件依然滿足,但更背離“最小長度”的要求
所以選擇收縮窗口,i 右移,直到條件不再滿足,所以這裏是一個循環
在循環中,將窗口長度和全局的最小比較
如果窗口不再 sum >= s ,此時應該擴張窗口,j 右移,直到條件重新滿足
移動窗口的套路
- 擴張窗口:找可行解,找到了就不再擴張
- 收縮窗口:在長度上優化該可行解,直到條件被破壞
- 尋找下一個可行解,然後再優化……
我們可以畫圖來理解,就是先一次循環依次放到sum中去和s進行判斷,如果大於的話,後指針不動,前指針往前i++,記錄當前窗口的長度,知道不滿足sum>=s這個條件,進行後指針j++,兩個循環嵌套即可。
四、代碼展示
/**
* @param {number} s
* @param {number[]} nums
* @return {number}
*/
// var minSubArrayLen = function(s, nums) {
// var i = 0;
// var sum = 0
// var minLen = Infinity
// for(let j = 0 ; j < nums.length ; j++){
// sum+=nums[j]
// while(sum>=s){
// minLen = Math.min(minLen,j-i+1)
// sum -= nums[i]
// i++
// }
// }
// return minLen === Infinity ? 0 : minLen
// };
const minSubArrayLen = (s, nums) => {
let minLen = Infinity;
let i = 0;
let j = 0;
let sum = 0;
while (j < nums.length) { // 主旋律是擴張,找可行解
sum += nums[j];
while (sum >= s) { // 間歇性收縮,優化可行解
minLen = Math.min(minLen, j - i + 1);
sum -= nums[i];
i++;
}
j++;
}
return minLen === Infinity ? 0 : minLen; // 從未找到可行解,返回0
};