力扣算法题总结-滑动窗口,对撞指针(二)

滑动窗口

209-Minimum Size Subarray Sum (对于滑动窗口(队列)和对撞指针的相似之处的理解)

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

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

1,大顶堆选出最大的数,依次弹出相加与target比较,循环条件是和小于target
2,数组中的元素不停的入队,直到总和大于等于 s 为止,接着记录下队列中元素的个数,然后再不停的出队,直到队列中元素的和小于 s 为止(如果不小于 s,也要记录下队列中元素的个数,这个个数其实就是不小于 s 的连续子数组长度,我们要记录最小的即可)。接着再把数组中的元素添加到队列中……重复上面的操作,直到数组中的元素全部使用完为止。使用指针实现队列

  public static int minSubArrayLen(int s,int[] nums) {
   
    	int lo=0,hi=0,sum=0,min=Integer.MAX_VALUE;//
    	while(hi<nums.length) {
   //hi指针记录了数组放入队列的次数,lo指针记录了数组弹出的次数
    		sum+=nums[hi++];
    		while(sum>=s) {
   
    			min=Math.min(min, hi-lo);//hi-lo是队列中数的数量
    			sum-=nums[lo++];
    		}
    	}
		return min==Integer.MAX_VALUE?0:min;
    	
    }

3,二分法查找,用数组sums[i]表示的是原数组nums前i个元素的和,题中说了“给定一个含有n个正整数的数组”,所以sums数组中的元素是递增的。找到sums[k]-sums[j]>=s,即sums[j]+s<=sums[k],因为元素递增,我们只需要求出sum[j]+s的值,使用二分法查找即可找到这个k。
4,直接使用窗口,每次往窗口添加元素来判断是否满足。先固定一个窗口大小length,遍历数组,查看在数组中length个元素长度的和是否有满足的,没有就扩大窗口,有就记录下来缩小窗口的大小length继续找。

public static int minSubArrayLen(int s,int[] nums) {
   
    	int lo=1,hi=nums.length,min=0;
    	while(lo<=hi) {
   
    		int mid=(lo+hi)>>1;//除以2的n次方
    		if(windowExist(mid,nums,s)) {
   
    			hi=mid-1;//找到就缩小窗口的大小
    			min=mid;//记录窗口最小值
    		}else
    			lo=min+1;//没找到就扩大窗口的大小
    	}
    	return min;
    }
    private static boolean windowExist(int size,int[] nums,int s) {
   
    	int sum=0;
    	for(int i=0;i<nums.length;i++) {
   
    	//从第i位开始往后加,加到限制大小还没有找到就找i+1,最后还没找到返回false
    		if(i>=size)
    			sum-=nums[i-size];
    		sum+=nums[i];
    		if(sum>=s)
    			return true;
    	}
    	return false;
    }

3-Longest Substring Without Repeating Characters

给定一个字符串,找出其中不含有重复字符的 最长子串 的长度。 输入: s = “pwwkew” 输出: 3 解释:
因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串,s由英文字母,数字,符号和空格组成。

依然是滑动窗口,即队列。

public int lengthOfLongerstSubstring(String s) {
   
    	if(s.length()==0)return 0;
    	//这里要用HashMap是因为,重复的元素不一定出现在左顶端
    	HashMap<Character,Integer>map=new HashMap<Character,Integer>();
    	int max=0;
    	int left=0;
    	for(int i=0;i<s.length();i++) {
   
    		if(map.containsKey(s.charAt(i))) {
   
    			left=Math.max(left, map.get(s.charAt(i))+1);
    			//把队列左边的重复元素移除,如果重复元素在最左端的右边就去除元素的左边所有元素
    			//移除其实就是移动指针指向的位置
    		}
    		map.put(s.charAt(i), i);//继续向map中添加元素
    		max=Math.max(max, i-left+1);//更新窗口大小
    	}
    	return max;
    }

340-Longest Substring with At Most K Distinct Characters

给定一个字符串 s ,找出 至多 包含 k 个不同字符的最长子串 T。

示例 :

输入: s = “eceba”, k = 2 输出: 3 解释: 则 T 为 “ece”,所以长度为 3。 示例 2:

输入: s = “aa”, k = 1 输出: 2 解释: 则 T 为 “aa”,所以长度为 2。

滑动窗口,初始时左右指针都指向0,用一个HashMap循环记录字符及频率,当不同字符数量过多,将左端字符取出,

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值