【Leetcode】代码随想录Day2|数组2.0

文章介绍了三种与数组操作相关的算法问题:有序数组的平方优化解法、长度最小子数组的滑动窗口策略以及螺旋矩阵的生成。通过双指针、滑动窗口和简洁的方向控制,作者提供了优化后的代码并分析了它们的时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成

977 有序数组的平方

初始思路

  1. 需要新建一个空list。双指针,找到第一个非负数作为起始点,左半边为负数,右半边为非负数,用left和right指针分别向左右两边找,对比大小,平方小的先append进新list。
  2. 用之前的双指针思路,最左和最右往中间找,对比大小,大的先append进list,最后将list reverse,利用[::-1]

问题:
第一个思路有些复杂,边界上面有很多需要仔细思考的地方,代码可优化空间很大。

class Solution(object):
    def sortedSquares(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        res = []
        idx = 0
        # 找到第一个非负数
        while idx < len(nums) and nums[idx] < 0:  
        # 一定要记得idx的范围,并且要写在nums[idx]之前,否则会out of boundary
            idx += 1
        
        left = idx - 1  # left = 非负数idx - 1 作为负数部分的指针
        right = idx
        while left >= 0 and right <= len(nums) - 1:
            left_sq = nums[left]**2
            right_sq = nums[right]**2
            if left_sq <= right_sq:
                res.append(left_sq)
                left -= 1
            else:
                res.append(right_sq)
                right += 1
        # 对单边条件剩余情况的处理
        if left >= 0:
            while left >= 0:
                res.append(nums[left]**2)
                left -= 1
        if right <= len(nums) - 1:
            while right <= len(nums) - 1:
                res.append(nums[right]**2)
                right += 1
        return res

优解与优化

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        l = 0
        r = len(nums)-1
        res = []
        while l<=r:
            if abs(nums[l])<abs(nums[r]):
                res.append(nums[r]**2)
                r -= 1
            else:
                res.append(nums[l]**2)
                l += 1
        return res[::-1]  # python list reverse complexity: O(n)

代码随想录:
Python 定义规定大小的数组:

res = [float('inf')] * len(nums)] # 需要提前定义列表,存放结果

Complexity
time: O(n)
space: O(n)

209 长度最小的子数组

初始思路
在看到滑动窗口的提示的时候想象到了类似双指针的移动窗口,但是想到的是遍历left指针,但这样会陷入和暴力解法相同的思路。因为时间有限,没有继续深入发散,直接看了解题思路。

参考思路后:
滑动窗口:遍历right指针,限制子数组发展的长度。

class Solution(object):
    def minSubArrayLen(self, target, nums):
        left = 0
        right = 0
        min_len = len(nums) + 1
        total = 0
        while right < len(nums):
            total += nums[right]
            if total >= target:
                while total >= target:
                    total -= nums[left]
                    left += 1
                sublen = right - (left-1) + 1
                if sublen < min_len:
                    min_len = sublen  
            right += 1
        if min_len < len(nums) + 1:
            return min_len
        return 0

代码随想录(优解优化):

class Solution:
    def minSubArrayLen(self, s: int, nums: List[int]) -> int:
        l = len(nums)
        left = 0
        right = 0
        min_len = float('inf')
        cur_sum = 0 #当前的累加值
        
        while right < l:
            cur_sum += nums[right]
            
            while cur_sum >= s: # 当前累加值大于目标值
                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

Complexity
time: O(n)
space: O(1)

59 螺旋矩阵II

初始思路
先建2D list。上行从左到右,右列从上倒下,下行从右到左,左列从下到上。
第一圈每边分别顺序写入n-1个数字,进入更内一圈,写(n-1)-2个数字。

代码随想录

class Solution:
    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          # 迭代次数、n为奇数时,矩阵的中心点
        count = 1                           # 计数

        for offset in range(1, loop + 1) :      # 每循环一层偏移量加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, startx, -1) : # 从下至上
                nums[i][starty] = count
                count += 1                
            startx += 1         # 更新起始点
            starty += 1

        if n % 2 != 0 :			# n为奇数时,填充中心点
            nums[mid][mid] = count 
        return nums

优解参考

  1. 方法一:从一开始填入数字,使用direction来改变方向。如果遇到边界或者非零的位置,则向右拐变换方向。
def generateMatrix(n: int) -> List[List[int]]:
        matrix = [[0] * n for _ in range(n)]
        num = 1
        row = 0
        col = 0
        direction = 0
        dr = [0, 1, 0, -1]
        dc = [1, 0, -1, 0]
        while num <= n * n:
            matrix[row][col] = num
            num += 1
            nextRow = row + dr[direction]
            nextCol = col + dc[direction]
            if nextRow < 0 or nextRow >= n or nextCol < 0 or nextCol >= n or matrix[nextRow][nextCol] != 0:
                direction = (direction + 1) % 4
            row += dr[direction]
            col += dc[direction]
        return matrix
  1. 方法一更简洁的写法:简化优化方向控制
class Solution(object):
    def generateMatrix(self, n):
        A = [[0] * n for _ in range(n)]
        i, j, di, dj = 0, 0, 0, 1
        for k in xrange(n*n):
            A[i][j] = k + 1
            if A[(i+di)%n][(j+dj)%n]:
                di, dj = dj, -di
            i += di
            j += dj
        return A

Complexity:
time: O(n^2)
space: O(1) 【因为题目要求建立n^2的数组,并不是算法本身需要的】

数组总结

数组小结,来自录友海螺人

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值