同向双指针_滑动窗口

前言:

这几天状态很差,每天晚上都睡不着。不知道是不是因为焦虑一些事情。总是觉得自己做的好不够好,时常怀疑自己。每天不知道在忙什么,论文、专利、上课、比赛。我真的有点挺不过去了。马上就是cmc初赛了,最少那个说着不在意就是去体验一下,可是真的甘心么?刚刚在群里看到了传智播客的大学生程序设计大赛,嘴上一直说着明年的程序设计大赛一定要雪耻。可真的到了,连这种含金量不高甚至被诸多人誉为"水赛"的比赛我现在都没有勇气去报。

思考一番,还是报名了。就当检验自己的实力了,也正当给自己一个鞭策。总是以为时间还长,自己还有许多机会。所以曾经的自己消磨了不知多少的时光,希望每个迷途知返的少年最后都能得到救赎。

因我自身能力有限,做这个博客一方面是为了自己复习,另一方面是想把自己的一些经验分享给大家。鄙人愚钝,敬请各位斧正。

随便记录的,希望不要影响读者。后续会出每个专题对应的知识点的讲解。

1.什么是同向双指针和滑动窗口?

上图:

 同向双指针和滑动窗口之间有什么关系呢?

 滑动窗口实际就是,通过两个同向指针之间的步幅差距来变成一个可以满足题目条件的矩形。

题目:

209.长度最小的子数组

https://leetcode.cn/problems/minimum-size-subarray-sum/description/

题目:

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

示例 1:

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

审题:

        1. n 个正整数的数组和一个正整数 target (都是大于0的)

        2.找出该数组中满足其总和大于等于 target 长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] 

        3.如果不存在符合条件的子数组,返回 0

思路1(暴力_Python易超时版):

假设nums = [2,3,1,2,4,3],挨个挨个数枚举。

 代码:
def minSubArrayLen(target, nums):
	n=len(nums)
	ans=n+1  # 因为题目中是要求最小值,所以初始一个最大值便于后面更新比较
	for i in range(n):
		total=0
		for j in range(i,n):
			total+=nums[j]  # 枚举求和
			if total >= target: # 题目条件:总和大于等于 target 的长度最小的 连续子数组
				ans=min(ans,j-i+1) # 更新值
				break
	return 0 if ans==n+1 else ans # ans==n+1 说明整个数组和都小于target值则返回0否则返回ans

思路2(同向双指针_滑动窗口):

en读题,连续的子数组,en可以想到滑动窗口。

 代码:

# 例如[2,3,1,2,4,3]
''' n1=2+3+1是小于7的,n2=2+3+1+2是大于7的,怎么缩小窗口喃,就减去left的值。那么为什么要减去left的值,因为首先题目要求的是连续的子串。所以只能减去左边left的值(left向右移动一位)然后看n2是否还大于7,如果还大于,则继续重复上述步骤。最后得到最小的ans值'''

def minSubArrayLen(target, nums):
	n=len(nums)
	left=0
	ans=n+1
	s=0
	for right,x in enumerate(nums):
		s+=x
		while s-nums[left]>=target:
			s-=num[left]
			left+=1
		if s>=target:
			ans=min(ans,right-left+1) '''判断这里right-left是否要+1--->想象right=left时,应该是有一位的而不是0'''
	return 0 if ans==n+1 else ans

 713.乘积小于k的子数组

https://leetcode.cn/problems/subarray-product-less-than-k/description/

题目:

给你一个整数数组 nums 和一个整数 k ,请你返回子数组内所有元素的乘积严格小于 k 的连续子数组的数目。

示例 1:

输入:nums = [10,5,2,6], k = 100
输出:8
解释:8 个乘积小于 100 的子数组分别为:[10]、[5]、[2],、[6]、[10,5]、[5,2]、[2,6]、[5,2,6]。
需要注意的是 [10,5,2] 并不是乘积小于 100 的子数组。

审题:

        1.整数数组 nums 和一个整数 k

        2.返回子数组内所有元素的乘积严格小于 k 的连续子数组的数目

思路(同向双指针_滑动窗口):

根据上述途中步骤模拟即可

代码:

# 还是同上一个题的同样问题,为什么大于目标值了除的是最左边的值
# 因为是一个连续的子数组
def numSubarrayProductLessThanK(nums,k):
        if k <= 1: # 因为题目中说的是数组重的值为正整数
            return 0
        n=len(nums)
        left=0
        ans=0
        total=1
        for right,x in enumerate(nums): # enumerate:枚举
            total*=x
            while total>=k:
                total /= nums[left]
                left+=1
            ans+=right-left+1
        return ans

 3.无重复字符的最长子串

https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/

题目:

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

审题:

        1.给定一个字符串 s

        2.找出其中不含有重复字符的 最长子串 的长度

思路1(切片更新):

相比于滑动窗口,这道题有一道更简单的方法就是---->切片更新

 代码:

def lengthOfLongestSubstring(s):
    n = len(s)
    ans = 0
    word = '' # 字符串加减
    for x in s:
        if x in word: # 判断
            word = word[word.index(x) + 1:] # 切片
        word += x
        ans = max(ans, len(word)) # 更新
    return ans

# word.index(x) + 1
# s='pwwkew'  word.index(p)=0  切片 从它的后一位开始切

思路2(滑动窗口+哈希集合):

代码:

from collections import Counter

def lengthOfLongestSubstring(s):
        n=len(s)
        ans=0
        cnt=Counter() # hashmap key:char val:int
        left=0
        for right,c in enumerate(s):
            cnt[c]+=1
            while cnt[c]>1:  # 判断字符出现次数
                cnt[s[left]] -= 1
                left+=1
            ans=max(ans,right-left+1)
        return ans

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值