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

977.有序数组的平方

coding tips:

  • 申请一个与已知数组同样大小的数组:new_nums = [float('inf')] * len(nums) 意思为:float('inf') → 创建一个无限大的浮点数; [float('inf')] → 变成一个数组;数组 * 一个大小 → 变成这个大小的一个数组。
  • 平方可表示为:i ** 2。
  • 初始赋值尽量写在一行。
  • 三指针,两个用于nums。一个用于new_nums。(名字你们自己定)

初始思路:刚开始只能使用暴力解法做,但是这种方法不符合“需要使用时间复杂度为O(n)的方法”,因此,看了一眼文字讲解非递减顺序的数组,“平方后的最大值只有可能在两边,不可能在中间”。OMG,醍醐灌顶,写了一版:(因为不对, bug没有找到,就不放代码了,只放图 ==)

课程:B站 卡哥 有序数组的平方

思路更新:进一步看了讲解,我发现我的思路没有问题,但是写法有问题!!1)申请一个同样大小的新数组。以前的写法会导致,在修改新数组时,就数组的值也会变,在未来解决问题时可以用new_nums = deepcopy(nums) 的方式解决,但是现在不需要哈。2)考虑的过于全面了,“等于”的情况可以归纳到“大于”或“小于”的任意一方,无需单另列出。3)每一步都要操作的步骤就可以提到判断外面(循环里面)进行【这是优化的点】。

代码:

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        left, right, j = 0, len(nums) - 1, len(nums) - 1
        # new_nums = nums 这样的直接赋值,修改new_nums时也会导致nums的变动
        new_nums = [float('inf')] * len(nums)  # 需要提前定义列表,存放结果

        while left <= right:
            # a = nums[right] * nums[right]
            # b = nums[left] * nums[left]

            if nums[right] ** 2 > nums[left] ** 2:
                new_nums[j] = nums[right] ** 2
                right -= 1
            else: 
                new_nums[j] = nums[left] ** 2
                left += 1
            # else: 
            # 此处无需额外将等于的情况单另出来,这样做会使最后指针错乱...反正这样case2没过
            #     new_nums[j] = a
            #     right -= 1
            #     new_nums[j] = b
            #     left += 1
            j -= 1 # 因为都需要做此操作,所以统一放在判断外面
        
        return new_nums

209.长度最小的子数组

coding tips:

  • min_L = float('inf')   # 将最小子序列最初赋值为一个最大值;
  • return subL if subL != float('inf') else 0    # 当在函数中的循环体结构中不好添加返回值时,函数整体的返回值也可以根据条件输出

初始思路:1)暴力解法:一个一个看 是否有>=的,二个二个,三个三个...只能说很麻烦;2)滑窗思想,运用了双指针,一个fast,一个slow,但是slow具体怎么移动有点混乱...写成下图:

课程B站 卡哥 长度最小的子数组

思路更新:值得肯定的是双指针的思想,有了“不够target就移动fast,多了就移动slow”的想法。在具体实现中需要加强,1)slow移动是一个连续的过程,使用if只能判断一次,不能找到最小子序列。2)fast与slow是两个分别移动的指针,因此需要两个循环!!3)因为要更新最小子序列,所以需要随时比较取最小,要学会用不影响大局观的小方法:min(A, B)。

代码:

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        # res:当前和,subL:最小子序列长度
        fast, slow, res, subL, n = 0, 0, 0, float('inf'), len(nums)

        while fast < n:
            res += nums[fast]

            while res >= target:
                subL = min(subL, fast - slow + 1)  # 判断当前子序列和两指针间距哪个小
                res -= nums[slow]  # 总和减去slow所指元素
                slow += 1  # slow向前移
            
            fast += 1
        
        # 如果不存在子序列就返回0,如果存在就返回subL
        return subL if subL != float('inf') else 0   

59.螺旋矩阵II

coding tips:nums = [[0] * n for _ in range(n)]   # 生成一个全是0的n*n的矩阵


初始思路:知道应该用左闭右开的区间写,但是不知道怎么画圈...以及也发现了中间会出现一个单个格子的情况,但是没有考虑到跟奇偶数相关。

课程B站 卡哥 螺旋矩阵 II

思路更新:优雅真是优雅!详见代码orz

代码

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        goal = 1
        start_x, start_y = 0, 0
        nums = [[0] * n for _ in range(n)]   # 生成一个全是0的n*n的矩阵
        offset = 1

        for loop in range(1, (n // 2) + 1):   # 循环几圈
            print(loop)
            # 从左到右
            for j in range(start_y, n - offset):
                nums[start_x][j] = goal
                goal += 1
            
            # 从上到下
            for i in range(start_x, n - offset):
                nums[i][n - offset] = goal
                goal += 1
            
            # 从右到左
            for j in range(n - offset, start_y, -1):
                nums[n - offset][j] = goal
                goal += 1
            
            # 从下到上
            for i in range(n - offset, start_x, -1):
                nums[i][start_y] = goal
                goal += 1
            
            # 换圈&边界值
            start_x += 1
            start_y += 1
            offset += 1
        
        # 中心赋值
        if n % 2 == 1:
            nums[start_x][start_y] = goal

        return nums

        


总结

数组的题型需要注意:

  • 区间问题
  • 一般都能用双指针解决问题
  • 数组的元素不能删除只能覆盖(c++思想)
  • 根据题目设置的前提来判断应该使用哪种方法
  • 24
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值