代码随想录算法训练营第二天 | 977:有序数组平方,209:长度最小数字和,59:螺旋数组

79 阅读2分钟

双指针的沿伸(从头尾向中间)

题目链接:977. Squares of a Sorted Array

昨天做了双指针的快慢指针运用,今天延伸到左右指针分别从数组两边靠拢。这一题题目中是有序数组,很经典的双指针运用。左右指针要新建数组来存储结果,直接覆写会污染原数组。

def sortedSquares(self, nums: List[int]) -> List[int]:
        left = 0
        k = right = len(nums)-1
        res = [0] * len(nums)
        while left <= right:
            if abs(nums[left]) < abs(nums[right]):
                res[k] = nums[right] * nums[right]
                right -= 1
            else:
                res[k] = nums[left] * nums[left]
                left += 1
            k -= 1
        return res

滑动窗口

题目链接:209. Minimum Size Subarray Sum

滑动窗口是双指针的再延伸,核心是设立一个条件来控制窗口中的元素满足要求,当不满足该条件时,左右边界会不断调整。209的滑动窗口看上去有三种状态:窗口内的和 < 目标,窗口内的和 > 目标,窗口内的和 = 目标;但在代码中,后面两种情况是合并的,他们都可以通过移动左边界来实现。

    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        lower = 0
        upper = 0
        prepSum = 0
        minLen = len(nums) + 1
        while upper < len(nums):
            prepSum += nums[upper]
            upper += 1 
            while prepSum >= target:
                minLen = min(minLen,upper-lower)
                prepSum -= nums[lower]
                lower += 1
        if minLen != len(nums) + 1:
            return minLen
        else:
            return 0

注意:滑动窗口的思想很简单,但是实际中确认控制条件和边界问题容易出错,尤其是在拓展的题目76里面(因为我个人写滑动窗口很容易出错,这里把76也放上来,76结合了字典的用法,推荐去做一做) 题目链接:76. Minimum Window Substring

def minWindow(self, s: str, t: str) -> str:
        need = defaultdict(int)
        needCnt = len(t)
        for i in t:
            need[i] += 1
        low = up = 0
        res = ""
        minLen = len(s)

        while up < len(s):
            if s[up] in need:
                need[s[up]] -= 1
                if need[s[up]] >= 0:
                    needCnt -= 1
                up += 1
            else:
                up += 1
            while needCnt <= 0:
                if s[low] not in need:
                    low += 1
                else:
                    need[s[low]] += 1
                    if need[s[low]] > 0:
                        needCnt += 1
                    low += 1
                prepLen = up - low + 1
                if prepLen <= minLen:
                    res = s[low-1:up]
                    minLen = prepLen
        return res

螺旋矩阵II

题目链接:59. Spiral Matrix II

螺旋矩阵本身不考察什么算法思想,主要就是对边界的控制。个人认为把每一圈的条件变成一样,不容易出现重复和越界的问题。以及在进入每一圈结束会回到该圈的原点,下一圈时注意要把起始点也放进去(x+1,y+1)

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        matrix = [[0]*n for _ in range(n) ]
        x = y = 0
        circle_num = n//2
        cur = 1
        m = n-1

        for i in range(circle_num):
            while x < m-i and y == i:
                matrix[y][x] = cur
                cur += 1
                x += 1
            while x == m-i and y < m-i:
                matrix[y][x] = cur
                cur += 1
                y += 1
            while x > i and y == m-i:
                matrix[y][x] = cur
                cur += 1
                x -= 1
            while x == i and y > i:
                matrix[y][x] = cur
                cur += 1
                y -= 1
            x += 1
            y += 1
        
        if  n%2 == 1:
            matrix[circle_num][circle_num] = cur
        
        return matrix