代码随想录算法训练营第二天|数组完结

207 阅读3分钟

977 有序数组的平方

**题目:leetcode.cn/problems/sq…

代码:

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        n = len(nums)
        l, r, i = 0, n-1, n-1
        res = [0] * n
        while l <= r:
            if nums[l] ** 2 > nums[r] ** 2:
                res[i] = nums[l] ** 2
                l += 1
            else:
                res[i] = nums[r] ** 2
                r -= 1
            i -= 1
        return res
            

解题思路: 一个非递减顺序的数组,可得平方最大值不是在最左边就是在最右边,所以最左边和最右边比,哪个大就写入新数组的最右边。

209 长度最小的子数组

**题目:leetcode.cn/problems/mi…

代码:

import math
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        left, right = 0, 0
        windows_sum = 0
        res= float("inf")

        while right < len(nums):
            windows_sum += nums[right]
            right += 1

            while windows_sum >= target:
                res = min(res, right - left)
                windows_sum -= nums[left]
                left += 1
        
        return 0 if res == float("inf") else res

解题思路: 这道题的关键在于使用滑动窗口算法。滑动窗口算法就是动态调整窗口的起始位置,先移动结束位置,直到窗口内满足条件,然后再移动起始位置,直到窗口内不满足条件,一直到快指针遍历完数组。个人理解,窗口就像个毛毛虫,先动头,再动尾,一直到头到达终点。以这道题为例,要找满足其和>=s的长度最小的连续子数组,就意味着,先移动快指针,直到窗口内的数组满足条件,然后再移动慢指针,直到窗口内的数之和不满足条件,这个时候要注意更新找到子数组的最小长度。然后快指针再动,慢指针再动,直到终点。

难点: 个人认为滑动窗口最难理解的就是这个窗口是个动态的,先要明确窗口里是什么,这道题窗口就是nums[left,right],然后要明确窗口滑动的条件是什么,windows_num > target,然后要注意窗口要扩大和收缩,这个过程中窗口要更新数据。 还要注意滑动窗口算法的时间复杂度是O(N),因为每个元素都进入和离开窗口一次,时间复杂度是2N。

59 螺旋矩阵||

**题目: leetcode.cn/problems/sp…

代码:

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        matrix = [[0 for _ in range(n)] for _ in range(n)]
        upper_bound, lower_bound = 0, n - 1
        left_bound, right_bound = 0, n - 1
        num = 1

        while num <= n * n:
            # 在顶部从左往右走
            for j in range(left_bound, right_bound+1, 1):
                matrix[upper_bound][j] = num
                num += 1
            upper_bound += 1 # 上边界向下缩

            # 在右边从上往下走
            for i in range(upper_bound, lower_bound+1, 1):
                matrix[i][right_bound] = num
                num += 1
            right_bound -= 1 # 右边界向左缩

            # 在下边从右往左走
            for j in range(right_bound, left_bound-1, -1):
                matrix[lower_bound][j] = num
                num += 1
            lower_bound -= 1 # 下边界向上缩

            for i in range(lower_bound, upper_bound-1, -1):
                matrix[i][left_bound] = num
                num += 1
            left_bound += 1

        return matrix

解题思路: 顺时针螺旋,就是一圈一圈往里走,每一圈分四步:在顶部从左往右走,在右边从上往下走,在下边从右往左走,在左边从下往上走,循环的边界条件写对就行。

难点: 要注意每走一步,对应的边界都要向里缩,比如走完“在顶部从左往右走”,上边界就要往里缩;然后就是注意每步写for循环的边界值,比如“在顶部从左往右走”,是range(left_bound, right_bound+1)而不是range(left_bound, right_bound),因为range是[left_bound, right_bound+1)。

今日感悟

连做题带写题解,大概用了两个半小时,主要是费在理解滑动窗口算法还是调试螺旋矩阵的边界值。感觉做题还是要把问题分解为小问题,然后再解决小问题,直到问题解决,想的过程中脑子要清醒,把步骤写下来再写代码。