タイトル説明
n個の正の整数と正の整数のターゲットを含む配列があるとします。
配列内の合計≥ターゲットを満たす最小の長さの連続サブ配列[numsl、numsl + 1、…、numsr-1、numsr]を見つけて、その長さを返します。条件を満たすサブ配列がない場合は、0が返されます。
例1:
入力:target = 7、nums = [2,3,1,2,4,3]
出力:2
説明:サブ配列[4,3]は、この条件下で長さが最小のサブ配列です。
例2:
入力:target = 4、nums = [1,4,4]
出力:1
例3:
入力:target = 11、nums = [1,1,1,1,1,1,1,1]
出力:0
問題解決のアイデア
スライディングウィンドウ法スライディングウィンドウ法
の一般的なロジック
int left = 0,right = 0;
while(right < s.length()){
//增大窗口
window.add(s[right]);
right++;
//debug
System.out.println("left:" + left +",right:" + right);
while(window needs shrink){
//缩小窗口
window.remove(s[left]);
left++;
//进行窗口内数据的一系列更新
}
}
テンプレートセットの最初に、次の4つの質問についてのみ考える必要があり
ます。1。ウィンドウを展開するために右に移動するとき、つまり文字を追加するとき、どのデータを更新する必要がありますか。
2.どのような条件下で、ウィンドウを一時停止して拡大し、左に移動してウィンドウを縮小する必要がありますか?
3.ウィンドウを縮小するために左に移動する場合、つまり文字を移動する場合、どのデータを更新する必要がありますか?
4.ウィンドウを拡大したとき、またはウィンドウを縮小したときに、結果を更新する必要がありますか?
スライディングウィンドウ方式
public int minSubArrayLen_1(int target, int[] nums) {
if (nums.length == 0 || target == 0)
return 0;
if (nums.length == 1 && target == nums[0]){
return 1;
}
int ans = Integer.MAX_VALUE;
int left = 0;
int right = 0;
int sum = 0;
while (right < nums.length){
sum = sum + nums[right];
while (sum >= target){
ans = Math.min(right - left + 1,ans);
sum = sum - nums[left];
left++;
}
right++;
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
暴力法
public int minSubArrayLen(int target, int[] nums) {
int min = Integer.MAX_VALUE;
for (int i = 0; i < nums.length; i++) {
int sum = nums[i];
if (sum >= target){
return 1;
}
for (int j = i + 1; j < nums.length; j++) {
sum += nums[j];
if (sum >= target){
min = Math.min(min,j - i + 1);
break;
}
}
}
return min == Integer.MAX_VALUE ? 0 : min;
}