[LeetCode]Minimum Size Subarray Sum
Posted 乘风有时
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LeetCode]Minimum Size Subarray Sum相关的知识,希望对你有一定的参考价值。
题目:Minimum Size Subarray Sum
给定一个整数数组,和一个值,找到一个连续子序列,使其和>=给定的值,且该子序列长度最短。
思路1:
时间复杂度O(n),空间复杂度O(1)的解法。
使用首尾两个指针,求出两个指针之间的数据之和;当和大于等于s时,比较序列长度和最小值,然后,增加头指针;当和小于s时,然后,增加尾指针;
注意:
1.数组整个之和小于s的情况;
2.循环退出条件是tail != nums.cend();它不能保证最后的子序列是最短状态。
int LeetCode::minSubArrayLen(int s, vector<int>& nums){ if (!nums.size())return 0; auto head = nums.cbegin(), tail = nums.cbegin() + 1; int min = nums.size(), cur = nums.at(0);//s可能是负值 while (tail != nums.cend()){ if (cur < s){//尾指针增加 cur += *tail; ++tail; } else{ if (min > tail - head)min = tail - head;//判断是否当前子序列更短 cur -= *head;//头指针增加 ++head; } } if (min == nums.size() && cur < s)return 0;//数组的总和仍小于s while (s <= cur){//最后子序列可能不是最优状态{7[2, 3, 1, 2, 4, 3]} cur -= *head; ++head; } if (min > tail - head + 1)min = tail - head + 1; return min; }
思路2:
时间复杂度O(nlogn),空间复杂度O(1)的解法。
滑动窗口的思想来解此问题。固定一个大小的窗口,从头到尾滑动该窗口,判断窗口里的元素之和>=s,返回true。
然后,通过折半的方式锁定窗口的大小,找到最小的窗口大小使得窗口中的元素之和>=s。
int LeetCode::minSubArrayLen2(int s, vector<int>& nums){ int i = 1, j = nums.size(), min = 0; while (i <= j) { int mid = (i + j) / 2;//窗口大小 if (windowExist(mid, nums, s)) { j = mid - 1;//存在,则收缩窗口 min = mid; } else i = mid + 1;//折半的方式锁定窗口大小 } return min; } bool LeetCode::windowExist(int size, vector<int>& nums, int s) { int sum = 0; for (int i = 0; i < nums.size(); i++) { if (i >= size) sum -= nums[i - size];//开始滑动 sum += nums[i]; if (sum >= s) return true; } return false; }
思路3:
时间复杂度O(nlogn),空间复杂度O(n)的解法。
这个思路需要辅助数组,用来保存给定的数组的前i项的数据之和。
循环所有元素,并且通过折半的方法找到当前位置开始到最近结束位置,使得该区间的元素之和>=s。
int LeetCode::minSubArrayLen3(int s, vector<int>& nums){ int sum = 0, ret = nums.size() + 1;//ret记录最小值 vector<int>& sums(nums);//前i项的和 for (int i = 0; i < nums.size(); i++) sums[i] = nums[i] + (i == 0 ? 0 : sums[i - 1]); for (int i = 0; i < nums.size(); i++) { //找到以当前位置开始和大于s的最近结束位置 int j = i, k = sums.size() - 1, offset = i == 0 ? 0 : sums[i - 1];//j从当前起始位置i开始,k作为尾指针前后往前,offset记录前一个的位置的和 while (j <= k) {//折半的方式找到最近结束位置 int m = (j + k) / 2; int sum = sums[m] - offset; if (sum >= s) k = m - 1; else j = m + 1; } if (j == nums.size()) break; ret = min(j - i + 1, ret);//更新最小值 } return ret == nums.size() + 1 ? 0 : ret; }
以上是关于[LeetCode]Minimum Size Subarray Sum的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode -- Minimum Size Subarray Sum
leetcode 209. Minimum Size Subarray Sum
leetcode - minimum size subarray sum
Leetcode 209: Minimum Size Subarray Sum