代码随想录算法训练营第二天 | Leetcode 209 长度最小的子数组 59 螺旋矩阵

        之前一直觉得leetcode刷的是对代码的熟练度,还有一些经典的数学算法。但做到今天发现更多的是一种思路,计算机专业的一些思考问题的想法。在都能用copilot写代码的今天,感觉这种想问题的方法是更重要的东西。

第一题:长度最小的子数组

        题目描述如下:

        看到这个题直接放弃,最直接的原因是不太会表示子集合。看了视频讲解,采用的是双指针法。视频的说法有点复杂,核心在于这个子数组的索引是连续的,比如[1,2,3]中,只认[1,2]和[2,3]为子数组,[1,3]就不算子数组了。这么一梳理思路就清晰了,写两个for循环嵌套。第一个循环用于所有的起始值,第二个循环用于截取窗口并判断窗口内的大小。令i从0开始取,j从0到n走len(nums)个,然后i从1开始取,j从1到n走len(nums)-1个,一直到i到n,此时j只有n可以走。可以看出来j的取值范围是(i,len(nums))。好的,那我就开始遍历,累加子数组的和为sum,创建一个空列表list1储存满足子数组和≥target的值时的长度。在每一次获得一次遍历j走完,要开启下一个i值的遍历时,将sum清零,存储新的一轮i值。最后,返回储存满足条件的子数组长度列表的最小值,如果列表为空的话,说明没有累加和≥target值的子数组,返回0。我的代码如下:

        暴力解法被制裁了,通过了18个用例,有一个很bt的用例,target超大,炸内存了。无奈只能看看官方题解。题解里也有类似的暴力法,并且明确提出python写这种方法会被针对。

        选择滑动窗口法,采用双指针left和right,都从0开始。先动right,当right小于l时,累加值cur_sum等于当前right的累加值,当累加值大于目标值时,取当前最小累加区间长度和右-左的数列片段中的最小值,作为新的累加区间长度,此时累加值要减去左边的值数,然后让左边的指针也动起来。这样可以进一步缩小区间,判断有没有更优的符合条件的最小长度。更新后的滑动窗口方法如下,我的理解是同样是双循环,第二个循环变成一个条件启动了,这样可以有效减免很多循环。采用双指针就是为了更好地不通过循环加来给出来这个条件。相应的,条件启动过后还要优化,因为本身条件启动会有一个考虑不全的问题,具体不全就不全在,前面的累加和算不上。

第二题:螺旋矩阵

        题目描述如下:

        ...让我想起了selective scan,刚好最近在看mamba的论文,不过还是不一样的,那个是像响尾蛇一样来来回回。这次看论文也打算写点博客了,感觉是要比自己手写笔记要方便一些。

        找规律吧,最中间的数[n-1,n-1]肯定是n^2,第一行是1到n,最右侧一列是n到2n-1,最下面是2n-1到3n-2。好的,别的看不出来了。

        看了答案,就是直接遍历,像贪吃蛇一样往下写就行。从(0,0)开始,offset初始设置为1,最终循环到n//2+1时截止。why这么设置?offset这里的理解就是转一圈,贪吃蛇右转四次为一圈(事实证明右转右转右转右转不会回到原位hhh)。先从左到右走,这时候改变的只有列值(平行于x轴),要走的路程都等于列数-1=n-1,每前进一个单位下一个蛋,每下一个蛋贪吃蛇就长一些,nums[startx][i](行数不变,列数前进),蛋数+1。然后转弯,该向下走了,此时列数是不变的,要走的路程从开始的startx(第0列)往下走n个。依然下蛋,以此类推,直到转回来为止。每一个循环结束后并没有回到原点,起始点要各+1,因此startx+1,starty+1,要走的路程随即减少。

        还有一个尴尬的问题,当n为奇数的时候,loop向下取整的,导致少转一圈,所以要填充一下中心值,中心值的索引是[mid,mid],填充值为现在出来的count。汇总代码如下:

        这个题,可能关键就在于这个offset的设计能不能想到,通过offset控制行走的路程,导致每次循环走的次数不一样,完美按照题目给出的路径走出来。另外,用-1控制从右到左、从下到上的反方向行走。最后,在横着走的时候列索引不变,行索引依次+1。在竖着走的时候行索引不变,列索引依次+1。

        明天再战,今天因为上班都没有看多少算法,倒是坚持了leetcode。其实还是应该把cv当成主业去做的,明天优先刷论文刷代码。

第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值