首先自己做法,想到了之前用的一个快速排序,于是解法:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int sum = 0;
int length = 0;
sort(nums.begin(), nums.end());
for (int i = nums.size() - 1; i >= 0; i--){
sum += nums[i];
if (sum >= target){
length = nums.size() - i ;
break;
}
}
return length;
}
};
但是该解法在第18个用例处报错了,不知道是什么原因
target =
213
nums =
[12,28,83,4,25,26,25,2,25,25,25,12]
添加到测试用例
输出
7
预期结果
8
费解,我手算这个结果也是7,在VSCODE中调试也没发现什么问题,用暴力解法运行竟然能过,我仔细研究下。
其次是暴力解法。
暴力解法看着看着我突然明白了,原来这题要的是“长度最小的子数组”,要是连号的,没仔细审题。。导致研究了这么久。下次一定要认真领会题目的意思。
这样的话暴力解法也不难理解,就是算出每一个i为起点的子序列的长度取最小即可。
滑动窗口法。这个名字一听就很牛逼,但是感觉和之前的快慢指针有异曲同工之妙。
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX; // 最终的结果
int sum = 0; // 子序列的数值之和
int subLength = 0; // 子序列的长度
int i = 0;
for (int j = 0; j < nums.size(); j++){
sum += nums[j];
while (sum >= s){
subLength = j - i + 1;
result = subLength < result ? subLength :result;
sum -= nums[i++];
}
}
return result == INT32_MAX ? 0 : result;
}
};
原理不难,但是实现的方式也很巧妙。就像一个滑动的窗口一样。利用一个for循环就满足了要求。先让窗口末端延申,延申到一个窗口大小之后,起点前移缩短窗口,然后再终点后移,一直保持着一个刚刚好的窗口大小遍历完所有的子数组,最后利用异或只保留最小的子数组长度即可。