【双索引技术 滑动窗口】leetcode209(c语言实现)

双索引技术

滑动窗口:两个索引表示的是一个窗口,我们让这个窗口不停的滑动,在数组中找到我们希望求的解。

 

leetcode 209

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

示例:

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

进阶:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum
 

题目示例分析:在数组中4,3满足sum>=s的条件而且是最短的,比如说1,2,4也满足条件但是是3个元素了,2,3,1,2这个连续子数组也满足条件 但是长度为4,在整个数组中4,3是最小的返回2.

思路:首先要先明白子数组的概念 子数组是数组中的部分元素可以是连续的也可以不连续本题中是连续子数组。还要考虑没有解怎么办,本题中返回0.。可以先考虑暴力求解遍历所有连续子数组[i,j],每一个起始的连续子数组都是被起始索引i和终止索引j决定的,我们需要使用双层循环一旦我们得到了一个连续子数组从i到j这个范围,我们还需要把范围内所有numbers相加起来计算和sum,验证sum>=s,如果验证成功则是满足条件的子数组,再看长度是不是比当亲、按找到的解小,时间复杂度O(n^3)。

优化:暴力解中存在大量重复操作 比如说遍历到了nums[i...j],我们可以很快的知道nums[i...j-1]的和只需要减去j上的元素即可。基于以上想法,可以设计出nums[i...j]的一个连续子数组。如果子数组和小于s把下一个元素拉进来 j++看nums[i...j+1]的和是否大于等于s,还不满足,继续向后看,以此类推。直到sum>s就找到了满足题意的连续子数组,把长度记录下来。从i这端开始缩小连续子数组i--,这样连续子数组的和就会小一些,到某一时刻sum<s,此时j索引继续向前行进找到一个连续子数组的和大于s,依次类推,如图这个窗口不是固定的是由i和j控制的,窗口不停的向前滑动来找到满足题意的连续子数组。这就是滑动窗口的意思。

 

#define min(a,b) a<b?a:b 
int minSubArrayLen(int s,int *nums,int numsSize)
{
	//时间复杂度O(n)索引l r 不断地向前推进遍历了一遍数组 空间复杂度O(1) 没有开辟新的数组 
	int l = 0,r = -1;//nums[l...r]为我们的滑动窗口,l=0 r=-1 初始为空 
	int sum  = 0;//窗口中元素的和
	int res = numsSize+1;//来记录当前找到最小连续子数组的长度 初始化为整个数组
	//长度+1 因为之后要逐渐求最小值,所以初始化设置为最大的 ,这个值是不可能取到的
	//一旦找到了一个满足题意的连续子数组只需要求 res和当前的长度求最小值就行了 
	while(l<numsSize)//左边界能取值右边界就能取值 还存在可能有的滑动窗口供我们选择 
	{
		if(r+1<numsSize&&sum<s)//r+1<numsSize  如果r已经到了最右侧就不能向前扩展了 
		{
			r++;
			sum+=nums[r];
			// 也可以写成 sum+=nums[++r];
		} 
		else
		{
			// 也可以写成 sum+=nums[l++];
			sum-=nums[l];
			l++;
		}
		if(sum>=s)//找到了一个连续子数组 nums[l...r]
		{// 把res和当前连续子数组长度作比较求最小值 
			res = min(res,r-l+1);//不断获得连续子数组的最小值 
		}
	}
	if(res == numsSize+1)//遍历一边数组没有解的情况 res没有更新也就是没有解 
	{
		return 0;
	}
	return res;
	
}	

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
滑动窗口是一种常用的算法技巧,可以用于解决一类问题,其中包括一些LeetCode上的题目。通过维护一个窗口,我们可以在线性时间内解决一些需要处理连续子数组或子字符串的问题。以下是一些常见的滑动窗口问题: 1. 最小覆盖子串(Minimum Window Substring):给定一个字符串S和一个字符串T,在S中找出包含T所有字符的最小子串。 2. 字符串的排列(Permutation in String):给定两个字符串s1和s2,判断s2是否包含s1的排列。 3. 找到字符串中所有字母异位词(Find All Anagrams in a String):给定一个字符串s和一个非空字符串p,找到s中所有是p的字母异位词的子串。 4. 替换后的最长重复字符(Longest Repeating Character Replacement):给定一个只包含大写英文字母的字符串s,你可以将一个字母替换成任意其他字母,使得包含重复字母的最长子串的长度最大化。 5. 至多包含两个不同字符的最长子串(Longest Substring with At Most Two Distinct Characters):给定一个字符串s,找出至多包含两个不同字符的最长子串的长度。 以上只是几个例子,滑动窗口可以应用于更多类型的问题。在解决这些问题时,我们通常使用两个指针来表示窗口的左右边界,并根据具体问题的要求移动窗口。在每次移动窗口时,我们可以更新窗口的状态,例如统计字符出现次数、判断窗口是否满足条件等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值