leetcode变长窗口,3无重复字符的最长子串;159至多包含两个不同字符的最长子串;209长度最小的子数组;487&1004最大连续1的个数;1208尽可能使字符串相等;904水果成篮

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

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        # Step 1: 定义需要维护的变量, 本题求最大长度,所以需要定义max_len, 
        # 该题又涉及去重,因此还需要一个哈希表
        max_len, hashmap = 0, {} 

        # Step 2: 定义窗口的首尾端 (start, end), 然后滑动窗口
        start = 0 
        for end in range(len(s)):
            
            # Step 3
            # 更新需要维护的变量 (max_len, hashmap)
            # i.e. 把窗口末端元素加入哈希表,使其频率加1,并且更新最大长度
            hashmap[s[end]] = hashmap.get(s[end], 0) + 1
            if len(hashmap) == end - start + 1: 
                #不重复的元素个数和字符子串当前长度一样,判断是否是历史最长的字符串
                max_len = max(max_len, end - start + 1)
            
            # Step 4: 
            # 根据题意,  题目的窗口长度可变: 这个时候一般涉及到窗口是否合法的问题
            # 这时要用一个while去不断移动窗口左指针, 从而剔除非法元素直到窗口再次合法
            # 所以需要不断移动窗口左指针直到窗口再次合法, 同时提前更新需要维护的变量 (hashmap)
            while end - start + 1 > len(hashmap): 
                head = s[start]
                hashmap[head] -= 1
                if hashmap[head] == 0:
                    del hashmap[head]
                start += 1
        # Step 5: 返回答案 (最大长度)
        return max_len

leetcode 159 至多包含两个不同字符的最长子串

给定一个字符串 s ,找出 至多 包含两个不同字符的最长子串 t ,并返回该子串的长度。

示例 1:

输入: “eceba”
输出: 3
解释: t 是 “ece”,长度为3。

class Solution:
    def lengthOfLongestSubstringTwoDistinct(self, s: str) -> int:
        n = len(s)
        char_count={} # key:字符 value:字符个数
        l=0
        res=0
        for r in range(n):
            char_count[s[r]]=char_count.get(s[r],0)+1

            if len(char_count)<=2: #最多只有两种字符 在此情况找最长字符
                res=max(res, r-l+1)

            while len(char_count)>2:# # l右移直到只有两种字符,同时更新字典
                char_count[s[l]]-=1
                if char_count[s[l]]==0:
                    del char_count[s[l]]
                l+=1
        return res

leetcode 209. 长度最小的子数组

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

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        n=len(nums)
        l,r=0,0
        curr_sum=0
        res=n+1
        for r in range(n):
            curr_sum+=nums[r]
            while curr_sum>=target:
                res=min(res,r-l+1)
                curr_sum-=nums[l]
                l+=1 
            
        return 0 if res==n+1 else res

leetcode 487 最大连续1的个数 II

给定一个二进制数组 nums ,如果最多可以翻转一个 0 ,则返回数组中连续 1 的最大个数。
示例 1:
输入:nums = [1,0,1,1,0]
输出:4
解释:翻转第一个 0 可以得到最长的连续 1。
示例 2:
输入:nums = [1,0,1,1,0,1]
输出:4

class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        n = len(nums)
        l=0 
        res=-1
        curr_sum=0
        for r in range(n):
            curr_sum+=nums[r]
            if r-l+1 <=curr_sum+1:
                res=max(res, r-l+1)
            while r-l+1 > curr_sum+1:
                curr_sum-=nums[l]
                l+=1        
        return res

1004. 最大连续1的个数 III

给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。
示例 1:
输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
示例 2:
输入:nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。

class Solution:
    def longestOnes(self, nums: List[int], k: int) -> int:
        n = len(nums)
        l=0
        curr_sum = 0
        res = 0
        for r in range(n):
            curr_sum+=nums[r]
            if r-l+1 <= curr_sum+k:
                res = max(res, r-l+1)
            while r-l+1 > curr_sum+k:
                curr_sum-=nums[l]
                l+=1
        return res

leetcode 1208 尽可能使字符串相等

给你两个长度相同的字符串,s 和 t。将 s 中的第 i 个字符变到 t 中的第 i 个字符需要 |s[i] - t[i]| 的开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。

用于变更字符串的最大预算是 maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。

如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。

如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0。

示例 1:
输入:s = “abcd”, t = “bcdf”, maxCost = 3
输出:3
解释:s 中的 “abc” 可以变为 “bcd”。开销为 3,所以最大长度为 3。
示例 2:

输入:s = “abcd”, t = “cdef”, maxCost = 3
输出:1
解释:s 中的任一字符要想变成 t 中对应的字符,其开销都是 2。因此,最大长度为 1。
示例 3:

输入:s = “abcd”, t = “acde”, maxCost = 0
输出:1
解释:a -> a, cost = 0,字符串未发生变化,所以最大长度为 1。

class Solution:
    def equalSubstring(self, s: str, t: str, maxCost: int) -> int:
        #abcd->bcdf maxCost=3; 最长长度为abc到bcd是1+1+1,此时cost是3
        #abcd->cdef maxCost=3; 最长长度为a到c或者b到d是2;cost是2,如果ab到cd,那么cost就是2+2=4
        #abcd->acde maxCost=0;最长长度是a到a是1,此时cost是0;注意这里不能是cd到cd,因为两个字符串的index对不上

        # ord('a')可以找到’a‘的ascii码
        n = len(s)
        cost = 0
        l=0
        max_length=0
        for r in range(n):
            cost+=abs(ord(s[r])- ord(t[r]))
            if cost<=maxCost:
                max_length=max(max_length,r-l+1)
            while cost > maxCost : # 一个可变长的窗口
                cost -= abs(ord(s[l]) - ord(t[l])) 
                l+=1      
        return max_length

leetcode 1493 删掉一个元素以后全为 1 的最长子数组

给你一个二进制数组 nums ,你需要从中删掉一个元素。
请你在删掉元素的结果数组中,返回最长的且只包含 1 的非空子数组的长度。
如果不存在这样的子数组,请返回 0 。
提示 1:
输入:nums = [1,1,0,1]
输出:3
解释:删掉位置 2 的数后,[1,1,1] 包含 3 个 1 。
示例 2:
输入:nums = [0,1,1,1,0,1,1,0,1]
输出:5
解释:删掉位置 4 的数字后,[0,1,1,1,1,1,0,1] 的最长全 1 子数组为 [1,1,1,1,1] 。
示例 3:
输入:nums = [1,1,1]
输出:2
解释:你必须要删除一个元素。

class Solution:
    def longestSubarray(self, nums: List[int]) -> int:
        #对于只删除了一个元素的子数组,滑动窗口的和=r-l+1-1=r-l
        #所以结果就是找到最长子数组,并且r-l=sum(子数组)
        n = len(nums)
        l = 0
        max_length = 0
        curr_length = 0
        curr_sum = 0
        for r in range(n):
            curr_sum+=nums[r]
            if curr_sum >= r-l: #因为必须要删除一个元素,所以curr_rum==r-l或者curr_sum==r-l+1
                max_length = max(max_length, r-l)
            while r-l > curr_sum:
                curr_sum-=nums[l]
                l+=1
        return max_length

leetcode 904 水果成篮

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
示例 1:
输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。
示例 2:
输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
示例 3:
输入:fruits = [1,2,3,2,2]
输出:4
解释:可以采摘 [2,3,2,2] 这四棵树。
如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。
示例 4:
输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。

class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        #n=len(fruits) 一共有n棵树;fruits[i]是水果种类;只能选择两种水果
        #从哪里开始采摘很重要,比如[3,3,3,1,2,1,1,2,3,3,4]
        #如果从第一个3开始采摘,那么只能采摘3 3 3 1,碰到下一个2就要停止
        #简化题目:对于nums,找到一个连续子数组,其中只有两种不同整数,找到最长子数组
        n=len(fruits)
        if n==1:
            return 1
        value_count = {}
        l , res = 0, 0
        for r in range(n):
            value_count[fruits[r]]=value_count.get(fruits[r],0)+1
            if len(value_count)<=2: #这里需要考虑[1,1,1,1]这种情况,所以不能用==2
                res = max(res, r-l+1)
            while len(value_count)==3:
                value_count[fruits[l]]-=1
                if value_count[fruits[l]]==0:
                    del value_count[fruits[l]]
                l+=1
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值