代码随想录二刷day2 209.长度最小的子数组(滑动窗口) 76.最小覆盖子串

代码随想录复习



209.长度最小的子数组(滑动窗口)

209.长度最小的子数组
复习一下滑动窗口,滑窗的复杂度还是O(n)的,等于说拿r 遍历了一下数组

首先,滑动窗口的板子

for r in range(len()):
    (在r滑动过程中,更新一下要维护的变量)
    while l <= r and 滑窗移动的条件:
        首先更新一下要维护的变量
        l += 1 (滑窗左边界右移动)
        

按着板子这道题应该能秒杀因为很简单

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

76.最小覆盖子串

76.最小覆盖子串
t字符串中每一位的数量达标,并且总体数量达标,窗口右移
所以需要一个t_wordict和一个总需求flag 参与控制窗口右移
具体的更新窗口变量的逻辑在代码对应部分有所体现

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        l, r = 0, 0
        t_wordict = collections.Counter(t)
        flag = len(t)
        min_len = len(s) + 1
        start, end = 0, -1
        for r in range(len(s)):
            ch = s[r]
            if ch in t_wordict:
                if t_wordict[ch] > 0: flag -= 1
                t_wordict[ch] -= 1
            while l <= r and flag == 0:
                if r-l+1 <= min_len:
                    min_len = r-l+1
                    start, end = l, r
                ch = s[l]
                if ch in t_wordict:
                    if t_wordict[ch] == 0: flag += 1
                    t_wordict[ch] += 1
                l += 1
        return s[start: end+1]

904.水果成篮

904.水果成篮
这道题需要记住的有两个点,

一个是dict可以用Counter,因为新的元素进字典不用创建,直接可以dict[‘ch’] += 1

一个是删除字典里的value值为0的元素可以用 dict.pop(‘ch’)

这道题意思是,窗口里不能出现超过两种元素,求这种窗口的最长长度。所以窗口的更新逻辑是窗口里的元素大于2,但是要注意一旦value为0,要删除它不然会占用元素个数

这道题的结果更新逻辑需要放在窗口右滑之后,因为右滑逻辑是 > 2所以不能在这个时候更新长度,需要在滑动调整之后,迭代较大的那个窗口长度值

class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        l, r = 0, 0
        fruits_dict = Counter()
        max_length = 0
        for r in range(len(fruits)):
            fruits_dict[fruits[r]] += 1
            while l <= r and len(fruits_dict) > 2:
                fruits_dict[fruits[l]] -= 1
                if fruits_dict[fruits[l]] == 0: fruits_dict.pop(fruits[l])
                l += 1
            max_length = max(max_length, r-l+1)
        return max_length 

59.螺旋矩阵2

59.螺旋矩阵2

还是先理清一下思路,这道题是转着圈去填数去模拟,那么一拿到这个题的第一反应是应该 有两种循环

思维阶梯step1:
第一种属于外层循环,控制转的圈数
通过找规律可以找到如果是22、33的话,转一圈就行,如果是44、55的话,转两圈;可以发现 外层loop = n // 2, while loop 就一圈圈的转,每转一圈 loop-1
如果n是奇数的话,需要最后填上最后一个位置 res[mid][mid], mid = n // 2

思维阶梯step2:
第二种属于内层遍历,什么意思呢,就是每一条边怎么填。
这里就需要用for了,可以看出,每一条边都坚持左闭右开的原则,这个图还不是很形象,如果是5*5的话就不一样了,每一圈loop之后,内层的for循环的开始位置和结束位置都需要移动一位,我们用startx, starty,表示横行和列的循环开始,一开始初始化为0从头开始;结束位置可以看出都需要提前一位,我们可以整一个offset, 一开始初始化为1,结束位置就是n - offset。 每绕一圈,startx, starty, 和 offset都需要+1

思维阶梯step3:
loop也就是绕圈结束后,如果n一开始是奇数,需要手动填最后的中心

有了这三步思维阶梯,就应该能够a出来,注意, startx, starty代表的含义,我习惯y代表列,x代表行, j代表列,i代表行
在这里插入图片描述

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        res = [[0] * n for _ in range(n)]
        loop, mid = n // 2, n // 2
        startx, starty, offset = 0, 0, 1
        cnt = 1
 
        while loop:
            loop -= 1
            for j in range(starty, n-offset):
                res[startx][j] = cnt
                cnt += 1
            for i in range(startx, n-offset):
                res[i][n-offset] = cnt
                cnt += 1
            for j in range(n-offset, starty, -1):
                res[n-offset][j] = cnt
                cnt += 1
            for i in range(n-offset, startx, -1):
                res[i][starty] = cnt
                cnt += 1
 
            startx += 1
            starty += 1
            offset += 1

        if n % 2 == 1: res[mid][mid] = cnt
        return res

螺旋矩阵1

54.螺旋矩阵
不想看答案了,直接仿照螺旋矩阵2写的;这道题相比上一道,多了一些不是方阵的情况,方阵的话很容易读出来,有奇数的行列的话我加了一些特判

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        m, n = len(matrix), len(matrix[0])
        loop = min(m//2, n//2)
        startx, starty, offset = 0, 0, 1
        res = []

        if m == 1: #只有一行的情况
            for j in range(len(matrix[0])):
                res.append(matrix[0][j])
            return res
        if n == 1: #有多行只有一列的情况
            for i in range(len(matrix)):
                res.append(matrix[i][0])
            return res

        while loop:
            loop -= 1
            for j in range(starty, n-offset):
                res.append(matrix[startx][j])
            for i in range(startx, m-offset):
                res.append(matrix[i][n-offset])
            for j in range(n-offset, starty, -1):
                res.append(matrix[m-offset][j])
            for i in range(m-offset, startx, -1):
                res.append(matrix[i][starty])
            
            startx += 1
            starty += 1
            offset += 1
        #绕圈完之后的特判
        if m == n and m % 2 == 1:   #3*3 or 5*5这种情况
            res.append(matrix[m//2][n//2])
        if m != n and (m%2==1 and n%2==0  or n%2==1 and m%2==0): #3*4 or 4*3的情况
            if m % 2 == 1:
                for j in range(starty, n-offset+1):
                    res.append(matrix[m//2][j])
            elif n % 2 == 1:
                for i in range(startx, m-offset+1):
                    res.append(matrix[i][n//2])
        if m != n and (m % 2 == 1 and n % 2 == 1):    #3*5 or 5*3的情况
            if m > n:
                for i in range(startx, m-offset+1):
                    res.append(matrix[i][n//2])
            else:
                for j in range(starty, n-offset+1):
                    res.append(matrix[m//2][j])
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值