代码随想录算法训练营第二天 | 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II、数组总结

80 阅读3分钟

977.有序数组的平方

代码随想录视频讲解

代码随想录文章讲解

暴力解法:平方后排序

# Time complexity: O(NlogN) (O(N) for square and O(NlogN) for sort)
# Space complexity: O(N) for python Timsort algorithm
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        return sorted([num**2 for num in nums])

左右指针

  • 数组特性:绝对值最大的元素一定在数组两端
  • 比较两端的数的绝对值,取较大的数的平方从尾部开始放入新数组
  • 更新指针
# Time complexity: O(N)
# Sapce complexity: O(N)# use for loop
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        left, right = 0, len(nums)-1
        res = [0] * len(nums)
        for i in range(len(nums) - 1, -1,  -1):
            if abs(nums[left]) < abs(nums[right]):
                res[i] = nums[right] ** 2
                right -= 1
            else:
                res[i] = nums[left] ** 2
                left += 1
        return res
​
# use while loop
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        left, right, i = 0, len(nums)-1, len(nums)-1
        res = [0] * len(nums)
        while left <= right:
            if abs(nums[left]) < abs(nums[right]):
                res[i] = nums[right] ** 2
                right -= 1
            else:
                res[i] = nums[left] ** 2
                left += 1
            i -= 1
        return res

209. 长度最小的子数组

代码随想录视频讲解

代码随想录文章讲解

暴力解法:双重循环枚举

  • 两层循环枚举所有可能的subarray
# Time complexity: O(N^3)
# Space complexity: O(1)
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        min_len = len(nums) + 1
        for i in range(len(nums)):
            for j in range(i, len(nums)):
                sum = 0
                for k in range(i, j+1):
                    sum += nums[k]
                if sum >= target:
                    min_len = min(min_len, j-i+1)
                    break
        return 0 if min_len == len(nums) + 1 else min_len

滑动窗口

  • 使用左右指针维护一个滑动窗口(subarray),用sum变量去记录窗口内的数字的和,min_len去记录符合条件的subarray的长度的最小值
  • 如果sum大于等于target,我们比较当前的窗口长度和min_len的数值,取较小的那一个。并且移除最左端的数字
  • 如果sum小于target,我们就向右加入一个数字进入窗口
  • 重复以上步骤直到右指针遍历完整个数组,如果min_len还是初始值,则说明没有找到符合条件的subarray,返回0。
# Time complexity: O(N)
# Space complexity: O(1)
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        left, right = 0, 0
        sum = nums[0]
        if sum >= target:
            return 1
        min_len = len(nums) + 1
        while left <= right and right < len(nums):
            if sum >= target:
                min_len = min(min_len, right - left + 1)
                sum -= nums[left]
                left += 1
            else:
                if right + 1 < len(nums):
                    right += 1
                    sum += nums[right]
                else:
                    break
        if min_len == len(nums) + 1:
            return 0
        return min_len
      
# use for loop to increase right pointer and while loop to increase left pointer
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        left = 0
        sum = 0
        min_len = len(nums) + 1
        for right in range(len(nums)):
            sum += nums[right]
            while sum >= target:
                min_len = min(min_len, right - left + 1)
                sum -= nums[left]
                left += 1
        if min_len == len(nums) + 1:
            return 0
        return min_len

59. 螺旋矩阵 II

代码随想录视频讲解

代码随想录文章讲解

模拟路线

  • 在左上角:向右走
  • 在右上角:向下走
  • 在右下角:向左走
  • 在左下角:向上走
# Time complexity: O(N^2)
# Space complexity: O(1) not include the result matrix
class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        res = [[0 for i in range(n)] for i in range(n)]
        num = 1
        row, col = 0, 0
        direction = 'right'
        while num <= n**2:
            res[row][col] = num
​
            if direction == 'right':
                # top-right
                if col == n-1 or res[row][col+1] != 0:
                    direction = 'down'
                    row += 1
                else:
                    col += 1
                    
            elif direction == 'down':
                # bottom-right
                if row == n-1 or res[row+1][col] != 0:
                    direction = 'left'
                    col -= 1
                else:
                    row += 1
​
            elif direction == 'left':
                # bottom-left
                if col == 0 or res[row][col-1] != 0:
                    direction = 'up'
                    row -= 1
                else:
                    col -= 1
​
            elif direction == 'up':
                # top-left
                if row == 0 or res[row-1][col] != 0:
                    direction = 'right'
                    col += 1
                else:
                    row -= 1
​
            num += 1
        return res
      
# use for loop to count layer
class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        res = [[0 for i in range(n)] for i in range(n)]
        num = 1
        layers = n // 2
        row, col = 0, 0
        for i in range(layers+1):
            # right: col++ []
            for col in range(i, n-i):
                res[row][col] = num
                num += 1
            # down: row++ (]
            for row in range(i+1, n-i):
                res[row][col] = num
                num += 1
            # left: col-- (]
            for col in range(n-2-i, i-1, -1):
                res[row][col] = num
                num += 1
            # up: row-- ()
            for row in range(n-2-i, i, -1):
                res[row][col] = num
                num += 1
        return res

数组问题解法总结

二分法

  • 在有序数组中,通过不断比较mid从而缩小目标区间
  • 注意区间的开闭

双指针

  • 快慢指针,相向指针

滑动窗口

  • 注意元素进出窗口对所求的东西的影响
  • 如何移动起始点和终点

模拟行为(矩阵)

  • 注意区间的开闭和边界的判断