算法训练营 Day 02| 双指针、滑动窗口

148 阅读2分钟

977.有序数组的平方

因为平方数的性质,可以用双指针从首尾开始遍历比较

思路:

创建一个新数组,给定长度为nums

双指针从首尾一起遍历nums,取较大者从后往前更新

def sortedSquares(self, nums: List[int]) -> List[int]:

    n = len(nums)
    ans = [0] * n
    l, r = 0, n-1
    i = n - 1

    while i >= 0:
        if nums[r] ** 2 >= nums[l] ** 2:
            ans[i] = nums[r] ** 2
            r -= 1
        else:
            ans[i] = nums[l] ** 2
            l += 1
        i -= 1
    
    return ans

209. 长度最小的子数组

连续子数组 -> 滑动窗口

超时的暴力思路:

def minSubArrayLen(self, target: int, nums: List[int]) -> int:
    
    n = len(nums)
    l = inf

    for i in range(n):
        sums = nums[i]
        for j in range(i, n):
            if j != i:
                sums += nums[j]
            if sums >= target:
                l = min(j - i + 1, l)
                break
    
    return l if l != inf else 0

有点遗忘滑动窗这个方法,归纳一下:

类似于双指针,取两指针间的集合

遍历终止位置,随之移动起始位置

滑动窗口的精髓:如何移动起始位置

  • 移动起始位置时,判断目前区间内是否满足要求,若满足则移动起始位置,若不满足则向后移动终止位置

注意,其实起始位置不用随着终止位置的遍历而初始化,因为遍历时本身已经扩大了范围

def minSubArrayLen(self, target: int, nums: List[int]) -> int:
    
    n = len(nums)
    l = inf
    sums = s = 0

    for i in range(n):
        # s = 0
        # summarization of the window
        sums += nums[i]
        # check if bigger than target
        while sums >= target:
            # print(sums, i, s)
            l = min(i-s+1, l)
            # move the start pointer
            sums -= nums[s]
            s += 1
    
    return l if l != inf else 0

59. 螺旋矩阵 II

模拟过程

注意判断边界条件,总结规律进行模拟

*随想录中代码

    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          # 迭代次数、n为奇数时,矩阵的中心点
        count = 1                           # 计数

        for offset in range(1, loop + 1) :      # 每循环一层偏移量加1,偏移量从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 :			# n为奇数时,填充中心点
            nums[mid][mid] = count 
        return nums


#### 数组小结

- 数组地址连续
- 数组的元素是覆盖进行修改的
- 经典方法:
    - 二分
    - 双指针
    - 滑动窗口
    - 模拟