算法训练第二天 | 数组 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II

LeetCode 977.有序数组的平方

题目链接

977.有序数组的平方

思路

第一反应 拿到每个元素分别平方一下,再做个弊(哦不是)再排个序

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            nums[i] = nums[i] ** 2
        return sorted(nums)

来吧正常的算法流程:走下双指针 思路就是用两个指针指向两头,因为两头的元素一定是最大的,然后按照谁大谁先的原则从后向前塞进定义的新数组,就完事了

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

这里会报“list assignment index out of range”是因为new_list是空的,不能从尾巴开始塞,所以只要不让新定义的数组是空的就行,我这里给他全写了0,就过了

new_list = [0 for i in range(len(nums))]

完整的代码

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        new = len(nums) - 1
        new_list = [0 for i in range(len(nums))]
        left, right = 0, len(nums)-1
        while left <= right:
            if (nums[left] ** 2) > (nums[right] ** 2):
                new_list[new] = nums[left] ** 2
                left += 1
                new -= 1
            else:
                new_list[new] = nums[right] ** 2
                right -= 1
                new -= 1
        return new_list

反思

如果卡哥不讲,我是万万想不到用双指针的思路的。写的时候还感觉小用到了一下左闭右闭的原则

LeetCode 209.长度最小的子数组

题目链接

209.长度最小的子数组

思路

一开始是想做两个指针,一个是用来指开始计算的位置,一个负责加后面的数字,两个for循环暴力解,但是没写出来
(原来的)(没整出来)

    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        min_length = len(nums)
        for i in range(len(nums)):
            length = 0
            sum = nums[i]
            while sum < target and ((i+1) < len(nums)):
                length += 1
                i += 1
                sum += nums[i]
            if min_length > (length + 1):
                min_length = length + 1
        return min_length

写出来了,但是超时(还是要再理一理…不对鸭感觉还是错的啊。。救命,谢谢了,我先用滑动窗口吧)

def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        min_length = len(nums)
        length = 0
        sum = 0
        for i in range(len(nums)):
            sum = 0
            j = i
            sum = nums[i]
            while j < len(nums):
                if sum >= target:
                    length = j - i + 1
                    if min_length > length:
                        min_length = length
                    break
                else:
                    sum += nums[i]
                    j += 1
        return min_length

这道题用的思想是滑动窗口,相比暴力是两个for,这里用一个for循环就可以搞定,时间复杂度是O(n)。思想是:一个指针指向窗口尾巴,让窗口内sum保持大于target并不断缩减起始的位置,直到<target就开始移动尾指针,直到结束

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        sum, i = 0, 0
        min_length = float("inf")
        for j in range(len(nums)):
            sum += nums[j]
            while sum >= target:
                min_length = min(min_length, j-i+1)
                sum -= nums[i]
                i += 1
        return 0 if min_length == float("inf") else min_length

反思

暴力想法嵌套两个for循环,换成滑动窗口仅一个for循环即可完成。这道题做了很久,思路大差不差但是就是无法通过,python的语法感觉写起来也不太顺,还是要多练练

LeetCode 59.螺旋矩阵II

题目链接

59.螺旋矩阵II

思路

第一反应 一点思路都没有
解答思想:按照四条边来塞数字,4个For循环,转圈次数作为循环大条件,用一个变量调整边距。以及要考虑如果是奇数,额外处理最中间的位置值

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        nums = [[0]*n for _ in range(n)]
        count = 1
        loop = n//2
        offset = 1
        startx, starty = 0, 0
        for offset in range(1, loop+1):
            for j in range(starty, n-offset):
                nums[startx][j] = count
                count += 1
            for i in range(startx, n-offset):
                nums[i][n-offset] = count
                count += 1
            for j in range(n-offset, starty, -1):
                nums[n-offset][j] = count
                count += 1
            for i in range(n-offset, startx, -1):
                nums[i][starty] = count
                count += 1
            startx += 1
            starty += 1
        
        
        if n%2 == 1:
            nums[n//2][n//2] = count
        return nums

反思

这题确实体现出了coding能力很薄弱,拿到题的时候思维很混乱,不知道怎么写对,只能套判断套判断套for,整不出来,从四条边的角度和对转圈的考虑确实给我很大帮助。勤能补拙吧
还漏了一个很重要的点,循环不变量原则,这道题的循环不变量处理,是对于每一圈四条边的处理,操作都是一样的,并且都实行左闭右开原则,这样不会乱也能保证代码简洁

数组总结

· 循环不变量:找到问题的突破口的方式之一,解决包括代码冗余的情况
· 二分法:对于有序的数组,进行查找非常便捷
· 滑动窗口:通过控制起始位置,控制窗口内的情况从而做出判断
` 双指针:用一个for解决两个for的问题很有帮助

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值