长度最小的子数组(方1:暴力循环(不推荐) 方2:双指针思路(左右窗口滑动:一个意思))

题目:

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。
如果不存在符合条件的连续子数组,返回 0。

示例: 

输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
进阶:

如果你已经完成了O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。

分析:

  1. 方法1:最先想到的肯定是暴力循环,遍历以数组中所有元素为 开头的 子数组,如果找到满足条件的,记录长度,并与当前记录的最小长度进行比较;
    伪代码:
数组中所有元素遍历:
	当前元素与后面每个元素求和(遍历后面每个元素):
		如果和 满足条件,记录当前子数组的元素个数
实现见下方 代码1(并没有优化代码,可能存在冗余)
  1. 方法2:上面这种暴力方法需要对于每个元素的每个组序列求和,时间复杂度为On^2;
    如何优化呢?
    如果我们在求得第一个满足条件的子序列时,不重新计算,而是将左侧第一个元素扔掉,判断当前的 sum,如果满足条件继续将左侧的第一个元素扔掉。。。。。。。。。这样一来,我们每次扔掉一个元素,当前的和即为以扔掉之后元素为起点的尚未满足条件(或刚刚满足条件)的子序列
    而如果扔掉后不满足,则将右侧指针/窗口向右移动即可;
    这种思路类似于双指针和滑动窗

实现:见下方代码2(其中 变量i即为右指针,left为左指针;)

代码1 :(ac)

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int m = nums.size();
        int min_count = INT_MAX;
        if(m == 0)
            return 0;
        
        for(int i = 0; i < m; i++)
        {
            int sum = nums[i];
            int count = 1;
            if(sum >= s){
                return count;
            }
            
            for(int j = i+1;j < m; j++)
            {
                count++;
                sum+= nums[j];
                if(sum >= s){
                    min_count = min(count,min_count);
                    cout << min_count<<endl;
                    break;
                }
                if(j == m - 1){
                    cout << "i = " << i << "j = " << j  << endl;
                    if(min_count == INT_MAX)
                        return 0;
                    break;
                }        
            }
            
            
        }
        
        return min_count;
    }
};

代码2:(ac)

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int m = nums.size();
        if(!m)
            return 0;
            
        int sum = 0, left = 0, min_count = INT_MAX, count = INT_MAX;
        for(int i = 0; i < m; i++)
        {
            sum+= nums[i];	// 每次循环将右侧窗口扩大

            while(sum >= s)	// 如果当前满足条件,记录count并将左侧窗口缩小
            {
                count = i - left + 1;
                min_count = min(min_count, count);

                sum-= nums[left];
                left++;
            }
        }

        return min_count==INT_MAX? 0:min_count;
    }
};

你可能感兴趣的:(algorithm,practice)