Day02 - 数组part2

. - 力扣(LeetCode)

209 长度最小的子数组

本题关键在于理解滑动窗口

第一遍写:
思路:首先看一个数能达成的,然后看看两个数相加能不能达成target,但怎么处理三个数或者更多数呢?
直接看视频了。

审题经验:发现很关键的一个点是我没有发现这个子数组是原本的数组的连续的一段“nums_l, nums_(L+1), ....” 下次审题就知道了。怪不得说暴力写法是双指针两个for循环。

 知识补充
":=" 号海象运算符,python原本需要把赋值和判断分开写,现在只需要一句话。

你用":="时,是如下所写的。
if (n:=len(a)) > 5:
    print(n) 
假如不用":=",则会这么写:
n = len(a)
if n > 5:
    print(n)
或者
if len(a) > 5:
    print(len(a))

算法思路:我的一个误区是,因为看到题目说“如果不存在符合条件的子数组,返回 0”,就在一开始把子数组长度这个变量设置成0了。然而,这只考虑了没找到的情况,没有考虑到找到多个的情况。
子数组,不止一个。要求最小值的话,肯定要初始化一个比所有子数组的值都大的值 ,用来取小比较的。所以这道题目中应该把长度初始化为len(nums)+1。

读题误区:“大于等于”,下意识觉得是等于了,唉。

这题的python解法不好找,贴一下:​​​​​

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        if nums is None or len(nums)==0: 
            return 0 
        i = j = 0 ## 初始化双指针
        sum = 0 # 累加和
        lenf = len(nums) + 1 # 子数组的初始长度,因为是找最小
        ##假设一个比所有可能答案都大的值来比小
        while(j < len(nums)): # j作为右边的指针,遍历数组
            sum = sum + nums[j]
            j += 1 # 每次右边指针右移
            while(sum >= target): # 加起来的值比target大了
            #说明找到了需要的
                lenf = min(lenf, j - i) #比小
                sum = sum - nums[i] # 减去最左边的数,可能减掉后还是比target大
                # 是为了应对[1,2,99,2,1,1,1,1]这种情况
                i += 1 # 左边指针右移
        if lenf == len(nums) + 1: # 没有找到的子数组满足条件
            return 0
        else:
            return lenf 

我感觉最开始这个if nums is None or len(nums) == 0还挺体现思想的。

另外,虽然有两个while,但是时间复杂度是O(n)而不是O(n^2)哦,时间复杂度看的是每一个元素被操作的次数。这里每个元素被右指针指到时操作一次,被左指针指到时操作一次,所以时间复杂度是2n,系数忽略,也就是O(n)。

算法误区:差点找到了需要的就return lenf了,忘了要再减掉左边的看看是否依然成立,这样就能找到最小的。

第二次写:

除了第一行的nums is None写成了 = None以外都写对了,说明理解正确了。
 

59. 螺旋矩阵 II

. - 力扣(LeetCode)
值得直接看答案的难度,但可以再想想。

        1,...,      n

        4n-4,      n+1

        ...              ...

        3n-2, ..., 2n-1

只能想到这里,但是每一个拐角都得重新判断的样子。看答案了。
感觉矩阵一直是我的盲点,看了答案也完全不会,现在学习一下。

本题并不涉及到什么算法,就是模拟过程。

算法思路:→↓←↑为一个循环,多画几个发现规律:n//2就是循环的次数。
需要控制每一条边遍历的长度,每次循环右边界收缩一位(使用变量offset控制)。

矩阵算法重点:因为矩阵就是行和列,所以都是从二维数组开始做。横着走改j,竖着走改i。

算法思路:一开始疑惑为什么有个mid,后面明白了,如果n为奇数的话,需要单独给矩阵最中间的位置res[mid][mid]赋值。

思路误区:startx和starty真的就是每次循环的最开始一个点,而不是每个边的起点。

语法: range(0, n, -1),在最后加一个“-1”,可以从n到0遍历。如果知道这个的话第一遍说不定就可以自己奋斗一下。

list = [ [0] * n for _ in range(n)] 
list=[表达式 for 变量 in 范围 if 条件]
这里_等效于 for i in range, 但是_在后面不会用到,所以只是占位符。

第二遍写
错误:矩阵初始化,记住是for_ in range(n)
错误:python3也没有i++和i--。另外现在的解法忽略offset的值也要改变了。
错误:↓和←都是n-offset开始而不是startx,starty开始。

第三遍写
错误:控制循环的for offset in range(1,, loop + 1)还是没写出来
错误:四条边还是有混淆搞错的地方,可以看出目前还是纯背。写的时候我就在想我不确定自己有真的掌握←和↑这两条的含义(虽然这次混淆的是↓和↑)。
错误:是loop + 1写成了loop -1,还是没正确理解。

第二天第四遍写
居然写对了,要记得nums[x][y],记得哪个是横坐标哪个是纵坐标。

-------------------------------------------------------------------------------------------------------------------
五毒神掌
刷题第一遍
1、5-10分钟:读题+思考,罗列所有思路。
2、有思路:开始做和写代码,控制时间AC在15-30分钟前。
3、不会的话不要纠结,马上看题解和写代码。
4、背诵、默写好的解法,达到熟练程度。

刷题第二遍
1、马上自己写提交。

刷题第三遍
1、过了一天后,再重新做题。
2、不同解法的熟练程度 专项练习

刷题第四遍
1、过了一周:反复回来练习相同题目

刷题第五遍
面试前一周恢复性训练
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值