代码随想录算法训练营day02| 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II | Sundri

977. 有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
示例 2:

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

  • nums 已按 非递减顺序 排序
  • 请你设计时间复杂度为 O(n) 的算法解决本问题

双指针算法 (O(N)时间复杂度)

case1: 数组里面全部是正数

case2: 数组里面左半边是负数,右半边是正数

case3: 数组里面全部都是负数

如何把这几个case全部整合到一起?

1.双指针,一个从头遍历,一个从尾遍历;

2.定义一个长度为 len(nums)的res数组

3.设置一个pos参数,pos = len(nums) - 1,逆序遍历

4. 两个指针对应的数值的平方进行比较,谁大,就放在pos的位置上,pos 不断的 -1 

如果是l指针大就 l+=1,如果是r指针大就 r-=1

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        n = len(nums)
        l,r = 0, len(nums)-1
        pos = len(nums) - 1
        res = [-1] * n
        while pos >= 0: # 这里最tricky的地方就是其实pos可以取到0
            if nums[l] * nums[l] > nums[r] * nums[r]:
                res[pos] = nums[l] * nums[l]
                l += 1
            elif nums[l] * nums[l] <= nums[r] * nums[r]:
                res[pos] = nums[r] * nums[r]
                r -= 1
            pos -= 1
        return res

易错点:

1. while 循环的终止条件应该是 while pos >= 0, 因为 pos 可以取到 0 的位置!!!

209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:

输入:target = 4, nums = [1,4,4]
输出:1
示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

# 初步思路:

使用deque来表示滑窗,同时使用cur_sum来统计窗口元素的和,如果 >= target, 就把窗口左侧向右移动;如果还没有达到target,就把窗口右侧不断向右移动

# 深入 思考:

但是窗口的表示,真的需要一个deque吗?本质上是不用的!

因为窗口的存在,是因为它满足了某个条件,在这个题目里,就是让 cur_sum >= target! 因此在这个情况下,我们就并不需要多此一举使用deque,而是可以直接定义cur_sum变量,用它和target的关系来表示窗口动态变化的过程。注意:元素离开窗口的时候,cur_sum -= nums[l] 即 cur_sum要把这个元素给去掉。

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        # O(N) -- 
        # O(N log N) -- 
        cur_sum = 0
        l = 0 
        min_dis = float('inf')
        for r in range(len(nums)):
            cur_sum += nums[r] # 不管三七二十一,窗口先放元素进来
            while cur_sum >= target: # 卧槽:题目是找满足 >= target 而非 = target ..
                cur_sum -= nums[l] 
                min_dis = min(min_dis, r-l+1)
                l += 1
        return min_dis if min_dis != float('inf') else 0

        # 收获:不需要通过 deque 来表示窗口
        # 因为窗口形成的本质是满足某一个条件,所以只要让条件满足,其实就是窗口形成 - 好像在说废话

易错点:

1. 窗口形成的条件是 cur_sum >= target 题目不是=target,而是>= target!!!

59. 螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:

输入:n = 1
输出:[[1]]

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        maxtrix = [[ n+1  for _ in range(n)] for _ in range(n)] # create a matrix 
        l,r,t,b = 0,n-1,0,n-1
        value = 1
        while l <= r and t <= b:
            # left to right
            for i in range(l,r+1):
                maxtrix[t][i] = value
                value += 1
            t += 1

            # top to buttom
            for i in range(t,b+1):
                maxtrix[i][r] = value
                value += 1
            r -= 1

            # right to left
            if t <= b and l <= r: # 为什么如果我在这里写 while 会报错呢?
                for i in range(r,l-1,-1):
                    maxtrix[b][i] = value
                    value += 1
                b -= 1

            # bottom to up:
            if t <= b and l<= r:
                for i in range(b,t-1,-1):
                    maxtrix[i][l] = value
                    value += 1
                l += 1
        return maxtrix

# 易错点:什么时候写while,什么时候写 if ?

1.遍历范围:我选择了左闭右闭的遍历方式,所以要在每个地方都+1或者-1

2.当前两个顺序 t += 1 和 r-=1 的时候,后两段代码就要重新考虑 l <= r 和 t <= b 保证没有越界

3.遍历(右到左,下到上)的时候,我写 while 循环,答案就会报错,只能写 if -- 为哈?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值