209長度最小的子數組(滑動窗口、二分查找)

1、題目描述

給定一個含有 n 個正整數的數組和一個正整數 s ,找出該數組中滿足其和 ≥ s 的長度最小的連續子數組,並返回其長度。如果不存在符合條件的連續子數組,返回 0。

進階:如果你已經完成了O(n) 時間複雜度的解法, 請嘗試 O(n log n) 時間複雜度的解法。

2、示例

輸入: s = 7, nums = [2,3,1,2,4,3]
輸出: 2
解釋: 子數組 [4,3] 是該條件下的長度最小的連續子數組。

3、題解

解法一:

基本思想:滑動窗口,時間複雜度O(n)空間複雜度O(1)

  • 使用滑動窗口[left,right],裏面所有元素之和爲sum
  • 如果sum<s,擴大窗口右邊界向右延伸,同時更新sum
  • 如果sum>=s,更新res,縮小窗口左邊界向右延伸,同時更新sum

解法二:

基本思想:二分查找,時間複雜度O(nlogn)空間複雜度O(n),只是提供另一種思路

  • 先將nums從第一個元素到最後一個元素依次累計疊加保存至sums數組,使得sums數組有序
  • 然後遍歷sums,查找出第一個大於等於s+sums[i-1]的位置bound,也就是說從i到bound的nums元素之和大於等於s
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
class Solution {
public:
	int minSubArrayLen(int s, vector<int>& nums) {
		//基本思想:滑動窗口,時間複雜度O(n),使用滑動窗口[left,right],裏面所有元素之和爲sum
		//如果sum<s,擴大窗口右邊界向右延伸,同時更新sum
		//如果sum>=s,更新res,縮小窗口左邊界向右延伸,同時更新sum
		if (nums.size() == 0)
			return 0;
		int res = INT_MAX, left = 0, right = 0, sum = nums[0];
		while (right < nums.size())
		{
			if (sum < s)
			{
				right++;
				if (right < nums.size())
					sum += nums[right];
			}
			else
			{
				res = min(res, right - left + 1);
				sum -= nums[left];
				left++;
			}
		}
		return (res == INT_MAX) ? 0 : res;
	}
};
class Solution1 {
public:
	int minSubArrayLen(int s, vector<int>& nums)
	{
		//基本思想:二分查找,時間複雜度O(nlogn)空間複雜度O(n),只是提供另一種思路
		//先將nums從第一個元素到最後一個元素依次累計疊加保存至sums數組,使得sums數組有序
		//然後遍歷sums,查找出第一個大於等於s+sums[i-1]的位置bound,也就是說從i到bound的nums元素之和大於等於s
		if (nums.size() == 0)
			return 0;
		int ans = INT_MAX;
		vector<int> sums(nums.size() + 1, 0);
		for (int i = 1; i <= nums.size(); i++)
			sums[i] = sums[i - 1] + nums[i - 1];
		for (int i = 1; i <= nums.size(); i++) {
			int to_find = s + sums[i - 1];
			//lower_bound返回大於或等於to_find的第一個元素位置
			auto bound = lower_bound(sums.begin(), sums.end(), to_find);
			if (bound != sums.end()) {
				ans = min(ans, static_cast<int>(bound - (sums.begin() + i - 1)));
			}
		}
		return (ans != INT_MAX) ? ans : 0;
	}
};
int main()
{
	Solution solute;
	int s = 7;
	vector<int> nums{ 2, 3, 1, 2, 4, 3 };
	cout << solute.minSubArrayLen(s, nums) << endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章