領釦-209 長度最小的子陣列 Minimum Size Subarray Sum MD
阿新 • • 發佈:2018-12-16
目錄
Markdown版本筆記 | 我的GitHub首頁 | 我的部落格 | 我的微信 | 我的郵箱 |
---|---|---|---|---|
MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | [email protected] |
領釦-209 長度最小的子陣列 Minimum Size Subarray Sum MD
***
目錄
===
長度最小的子陣列 Minimum Size Subarray Sum -209
問題
給定一個含有 n 個正整數的陣列和一個正整數 s ,找出該陣列中滿足其和 ≥ s
的長度最小的連續子陣列
。如果不存在符合條件的連續子陣列,返回 0
。
示例:
輸入: s = 7, nums = [2,3,1,2,4,5]
輸出: 2
解釋: 子陣列 [4,5] 是該條件下的長度最小的連續子陣列。
進階:
如果你已經完成了 O(n)
時間複雜度的解法, 請嘗試 O(n log n)
時間複雜度的解法。
暴力法
class Solution { public int minSubArrayLen(int s, int[] nums) { int len = Integer.MAX_VALUE, tem; for (int i = 0; i < nums.length; i++) { tem = 0; for (int j = i; j < nums.length; j++) { tem += nums[j]; if (tem >= s) { len = Math.min(len, j - i + 1); break; } } } return len == Integer.MAX_VALUE ? 0 : len; } }
時間複雜度:O(n^2)
空間複雜度:O(1)
暴力法稍加改進(然並卵)
class Solution { public int minSubArrayLen(int s, int[] nums) { int len = Integer.MAX_VALUE, tem; for (int i = 0; i < nums.length; i++) { tem = 0; for (int j = i; j < nums.length && j < i + len - 1; j++) { tem += nums[j]; if (tem >= s) { len = j - i + 1; break; } } } return len == Integer.MAX_VALUE ? 0 : len; } }
時間複雜度:O(n^2)
空間複雜度:O(1)
雙指標法(推薦)
我們需要定義兩個指標left和right,分別記錄子陣列的左右的邊界位置,然後我們讓right向右移,直到子陣列和大於等於給定值或者right達到陣列末尾,此時我們更新最短距離,並且將left向右移一位,然後再sum中減去移去的值,然後重複上面的步驟,直到right到達末尾,且left到達臨界位置,即要麼到達邊界,要麼再往右移動,和就會小於給定值
class Solution {
public int minSubArrayLen(int s, int[] nums) {
int len = Integer.MAX_VALUE, left = 0, sum = 0;
for (int right = 0; right < nums.length; right++) {
sum += nums[right]; //左指標不動,右指標一直向右移動
while (sum >= s) {
len = Math.min(len, right - left + 1); //當滿足條件時先記錄一下當前需要的長度
sum -= nums[left++]; //然後左指標向右移動(移動過程中如果滿足條件則長度-1),直到不滿足條件(繼續移動右指標)
}
}
return len == Integer.MAX_VALUE ? 0 : len;
}
}
時間複雜度:O(n)
空間複雜度:O(1)
二分查詢法(不懂)
思路是,我們建立一個比原陣列長一位的sums陣列,其中sums[i]
表示nums陣列中[0, i - 1]
的和,然後我們對於sums中每一個值sums[i]
,用二分查詢法找到子陣列的右邊界位置,使該子陣列之和大於sums[i] + s
,然後我們更新最短長度的距離即可。
class Solution {
public int minSubArrayLen(int s, int[] nums) {
int len = nums.length, res = len + 1;
int[] sums = new int[len + 1];
for(int i = 1; i<len+1; i++){
sums[i] = sums[i-1] + nums[i-1];
}
for(int i = 0; i<len+1; i++){
int right = searchRight(i+1, len, sums[i]+s, sums);
if(right == len + 1) break;
if(res > right - i) res = right - i;
}
return res == len + 1?0:res;
}
private int searchRight(int left, int right, int key, int sums[]){
while(left <= right){
int mid = (left + right)/2;
if(sums[mid] >= key){
right = mid - 1;
}else{
left = mid + 1;
}
}
return left;
}
}
2018-12-16