给定一个数组nums以及一个s,找出在nums中 >= s的长度最小的连续子数组,并返回其长度。
1、前缀和 + 二分查找
首先想到的是暴力解法,第一个循环枚举子数组的左端点,第二个循环枚举右端点,同时维护一个最小的ans。
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = i; j < n; j++) {
sum += nums[j];
if (sum >= s) {
ans = Math.min(ans, j - i + 1);
break;
}
}
}
此方法复杂度为O(n2),但是我们可以想到,当确定了左端点时,查找其元素和> s的子数组,可以用二分查找方法,降低复杂度。
具体来说,我们可以先O(n)方法初始化一个前缀和数组prefix,其prefix[i]表示前i 个元素的和,则子数组 [i,j)的和为 prefix[i] - prefix[j-1]。
所以待查找的子数组,如果左端点为 i ,右端点位置为 j ,并且其元素和 > s, 可以表示为 prefix[j] - prefix[i-1] >= s,我们转移一下这个公式为 prefix[j] >= prefix[i-1] + s。显而易见,第一个循环是枚举左端点,然后再在prefix数组中,用二分查找的方法,查找第一个 >= prefix[i-1] + s的端点,则可以确定右端点。
int solve2(int s, vector<int> nums){
int ans = INT_MAX;
int n = nums.size();
if (n == 0) {
return 0;
}
vector<int> prefix(n+1, 0);
// prefix[i] 指的是 前i个数之和
for(int i = 1;i <= n;i++){
prefix[i] = prefix[i-1] + nums[i-1];
}
for(int i = 1;i <= n;i++){
int sum = s + prefix[i-1];
int bound = lower_bound(prefix.begin(), prefix.end(), sum) - prefix.begin();
if (bound < n+1) {
ans = min(ans, bound-i+1);
}
}
return ans == INT_MAX ? 0 : ans;
}
2、双指针方法
其基本思路是,左指针右指针初始指向0,每次右指针右移,如果其元素和 >= s则不断左移左指针,目的是维护最短的子数组。直到右指针指向最终元素为止。
举例说明 :
nums = 2 3 1 2 4 3
s = 7
int solve(int s, vector<int> nums){
int ans = INT_MAX;
int l = 0, r = 0;
int n = nums.size();
int sum = 0;
if (n == 0) {
return 0;
}
while(r < n){
sum += nums[r];
while (sum >= s) {
ans = min(ans, r-l+1);
sum -= nums[l];
l ++;
}
r ++;
}
return ans;
}
因为python是每个人必须会用的语言,所以也用python实现了一遍。
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
if not nums:
return 0
n = len(nums)
l, r = 0, 0
res = 0
ans = n + 1
while r < n:
res += nums[r]
while res >= s:
ans = min(ans, r-l+1)
res -= nums[l]
l += 1
r += 1
return 0 if ans == n+1 else ans
1、双指针的用法,双指针在LeetCode中经常出现,需要学会其使用方法。每个循环中更新右指针,其中一个循环不断更新left。
2、vector的更新方式,vector< int> demo(n, m),其中的n指的是n个元素,需要注意这里的n需要提前进行赋值;m是对demo中每个元素的赋值。
3、前缀和 + 二分查找的方法,要推出公式,说明一个思路并不是空穴来风,而是经过手推公式后发现的。
4、Python语法
(1)判断列表为空 if not nums
(2)全局变量 + 局部变量。
函数内部的变量在 = 前出现,则被认为是一个局部变量
如果是在函数内使用变量,则全局有定义,认为是使用全局变量
在函数内声明全局变量,要使用 global 关键字
(3)ans – 这种语法不被允许,应该是 ans -= 1
(4)return ans == n+1 ? 0 : ans 这是在C++中的用法
return 0 if ans == n+1 else ans 这是python中的用法
(5)python交换两个变量的值 a, b = b, a。
但需要注意,python交换两个变量时,先计算等号右边的值,得到一个元组,然后再按照从左到右的顺序 给 左边两个值赋值。所以有时候需要注意顺序。