算法训练营day2

977.有序数组的平方

题目建议: 本题关键在于理解双指针思想

 题目链接:. - 力扣(LeetCode)

文章讲解:代码随想录

视频讲解: 双指针法经典题目 | LeetCode:977.有序数组的平方_哔哩哔哩_bilibili 

第一想法

暴力排序

一开始先用for循环,再用归并排序,发现超时了

然后直接用python自带的快速排序

def sortedSquares(self, nums: List[int]) -> List[int]:
         return sorted(num * num for num in nums)

复杂度 O(nlogn)

推荐算法

双指针法

核心思想:负数数组平方之后可能变成最大值,只能在数组的两边,不会在中间。因此使用双指针比较左右两个数的大小。

def sortedSquares(self, nums: List[int]) -> List[int]:
        left, k, right = 0, len(nums)-1, len(nums)-1
        res = [float('inf')] * len(nums)
        while k >= 0:

            if nums[right] ** 2 >= nums[left] ** 2:
                res[k] = nums[right] ** 2
                right -= 1
                k -= 1 
            else:
                res[k] = nums[left] ** 2
                left += 1
                k -= 1
        return res

209.长度最小的子数组

题目建议:本题关键在于理解滑动窗口思想

 题目链接:. - 力扣(LeetCode)

文章讲解:代码随想录

视频讲解:拿下滑动窗口! | LeetCode 209 长度最小的子数组_哔哩哔哩_bilibili

自己看到题目的第一想法

之前接触过类似题目,因此选择滑动窗口来做

debug过程中发现几个错误点:

1. 第一重while循环边界条件,不需要left < length, 仅需要right<length即可

2. 第二重判断cur_sum与目标值的大小,需要用一个while循环来不断地减去left指针的数字

3. min_len 初始设置需要设置为float('inf'),我一开始设置为0,导致每次min操作都得到0

4. 返回值时,如果min_len初始值没有被改变,则直接返回0

看完代码随想录之后的想法

想法是一样的,但是我自己具体代码实现过程问题比较大,参考代码随想录修改了自己的代码

def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        left,right=0,0
        cur_sum = 0
        min_len = float('inf')
        length = len(nums)
        while right < length:
            cur_sum += nums[right]
                
            while cur_sum >= target:
                min_len = min(min_len,right-left+1)
                cur_sum -= nums[left]
                left += 1
            right += 1
        return min_len if min_len != float('inf') else 0

59.螺旋矩阵II

题目建议: 本题关键还是在转圈的逻辑,在二分搜索中提到的区间定义,在这里又用上了。

题目链接:. - 力扣(LeetCode)

文章讲解:代码随想录

视频讲解:一入循环深似海 | LeetCode:59.螺旋矩阵II_哔哩哔哩_bilibili

自己看到题目的第一想法

创建两个数组,一个用来赋值,一个用来标记是否访问过

按照右,下,左,上的顺序依次赋值,两层while循环嵌套

def generateMatrix(self, n: int) -> List[List[int]]:
        nums = [[1]*n for i in range(n)] 
        label = [[0] * n for i in range(n)]
        cur_num = 1
        i = 0
        j = 0
        nums[i][j] = cur_num
        label[i][j] = 1
        while cur_num <= n**2:
            while ((j + 1) < n and label[i][j+1] == 0):
                j += 1
                cur_num += 1
                nums[i][j] = cur_num
                label[i][j] = 1
            
            while ((i+1) < n and label[i+1][j] == 0):
                i += 1
                cur_num += 1
                nums[i][j] = cur_num
                label[i][j] = 1
            while ((j-1) >= 0 and label[i][j-1] == 0):
                j -= 1
                cur_num += 1
                nums[i][j] = cur_num
                label[i][j] = 1
            while ((i-1) >= 0 and label[i-1][j] == 0): 
                i -= 1
                cur_num += 1
                label[i][j] = 1
                nums[i][j] = cur_num
            if cur_num == n**2:
                break
        return nums

看完代码随想录之后的想法

代码随想录中使用了二分法的原则, 而我的代码是使用了边界判断和label判断,空间复杂度要高一些

使用二分法 坚持循环不变量的原则;画四条边,每条边都坚持左闭右开的原则;每条边走长度的一半。(这个想法很神奇,需要一点观察力);需要注意每次大循环后,x和y的起始点要+1

def generateMatrix(self, n: int) -> List[List[int]]:
        nums = [[0] * n for _ in range(n)]
        startx, starty = 0, 0
        loop, mid = n//2, n//2
        count = 1

        for offset in range(1, loop+1): #每循环一层偏移量+1
            for i in range(starty, n-offset): # 从左到右
                nums[startx][i] = count
                count += 1
            for i in range(startx, n-offset): #从上到下
                nums[i][n-offset] = count
                count += 1
            for i in range(n - offset, starty, -1) : # 从右至左
                nums[n - offset][i] = count
                count += 1
            for i in range(n-offset, starty, -1): #从下到上
                nums[i][starty] = count
                count += 1
            startx += 1 # 更新起始点 进入内层循环了
            starty += 1           

        if n % 2 != 0: #当n为奇数时,填充中心点
            nums[mid][mid] = count
        return nums 
但是这个代码的时间消耗和空间消耗都大于我自己写的代码

总结

主要练习了双指针,滑动窗口,二分法

文章链接:代码随想录

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值