代码随想录day2:数组02(双指针,滑动窗口,转圈)

1. 双指针(leetcode 977 有序数组的平方)

双指针算法是一种在遍历对象时,使用两个或多个指针进行遍历及相应的操作的算法技巧。这种算法利用了数组的连序性特点,常用于降低算法的时间复杂度,因为它可以避免多层循环,从而简化一些运算。双指针算法的核心思想在于使用两个指针进行遍历,这些指针可以是相同方向(快慢指针)或相反方向(对撞指针)的指针,以达到特定的目的。

双指针算法的常见应用包括:

  • 在一个序列中,用两个指针维护一段区间。
  • 在两个序列中,一个指针指向其中一个序列,另一个指针指向另一个序列,以维护某种次序。

双指针算法的三种关键点包括:

  • 指针的起始位置的选取。
  • 指针的移动方向。
  • 指针的移动速度。

双指针算法的模型包括对撞指针、快慢指针、滑动窗口和归并排序等,这些模型展示了双指针算法在不同场景下的应用。

因为这题数组中的元素有正有负,所以平方后最大的元素只可能出现在头尾两侧,因此这题可以运用相反方向的双指针法,两个指针分别指向头尾,移动速度为一次一个元素,朝中间方向移动,对比两个指针平方后的大小然后进行排序。

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        first = 0
        second = len(nums) - 1
        new = [0] * len(nums)
        count = 0
        while first <= second:
            if nums[second] ** 2 > nums[first] ** 2:
                count -= 1
                new[count] = nums[second] ** 2
                second -= 1
            else:
                count -= 1
                new[count] = nums[first] ** 2
                first += 1
        return new

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

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

滑动窗口大致分为两类:一类是窗口长度固定的,即left和right可以一起移动;另一种是窗口的长度变化(例如前五道题),即right疯狂移动,left没怎么动,这类题需要观察单调性(即指针)等各方面因素综合思考

在本题中实现滑动窗口,主要确定如下三点:

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        first = 0
        second = 0                #定义两个指针位置
        answer = float('inf')     #使用inf来初始化窗口长度
        cumsum = 0           #使用cumsum来记录总和,避免使用sum浪费时间 
        while second < len(nums):     #loop完成条件为第二个指针遍历完所有元素
            cumsum += nums[second]
            while cumsum >= target and (second - first >= 0):
                answer = min(answer, second - first + 1)
                cumsum -= nums[first]
                first += 1
            second += 1
        return answer if answer != float('inf') else 0
#这道的重点在于右侧满足条件时,要对左侧窗口进行微调,所以需要两个while loop
#因为每个元素只被前后两个指针遍历两次,所以是O(n)

这道的重点在于右侧满足条件时,要对左侧窗口进行微调,所以需要两个while loop

虽然有两个while loop,但因为每个元素只被前后两个指针遍历两次,所以是O(n)

3. 转圈(leetcode 59:螺旋矩阵 2)

这道题目可以说在面试中出现频率较高的题目,本题并不涉及到什么算法,就是模拟过程,但却十分考察对代码的掌控能力。
在求解本题时一定要注意loop中的loop invariant,要处理好边界条件,才不会出错一直debug。

每个颜色为每次遍历的部分,一定要注意每个拐角边际条件的处理。

loop在这边坚持左闭右开原则。

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        nums = [[0] * n for _ in range(n)]
        startx, starty = 0,0
        loop, mid = n//2, n//2
        count = 1
        for offset in range(1, loop+1):
            for i in range(starty, n-offset):
                nums[startx][i] = count
                count += 1
            for i in range(startx, n-offset):
                nums[i][n-offset] = count
                count += 1
            for i in range(n-offset, starty, -1):
                nums[n-offset][i] = count
                count += 1
            for i in range(n-offset, startx,-1):
                nums[i][starty] = count
                count += 1
            startx += 1
            starty += 1
        if n % 2 != 0:
            nums[mid][mid] = count
        return nums

参考资料:

算法——滑动窗口_滑动窗口算法-CSDN博客

搜索智能精选

代码随想录

  • 23
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值