代码随想录 Day2 | Leetcode997 有序数组的平方、Leetcode209 长的最小的子数组、Leetcode59 螺旋矩阵2

上题

977. 有序数组的平方 - 力扣(LeetCode)

209. 长度最小的子数组 - 力扣(LeetCode)

59. 螺旋矩阵 II - 力扣(LeetCode)

第一题

给你一个按 非递减顺序 排序的整数数组 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]

 第一眼,一个sort()函数搞定。。。。时间复杂度n*log2^n,不满足要求

    def sortedSquares(self, nums):
        """
        第一遍,凭第一感觉解
        """
        for i in range(len(nums)):
            nums[i] = nums[i]**2
        nums.sort()
        return nums

思路

  • 正数序列平方最大值在最右边,负数序列最大值平方在最左边,双指针指向头尾,分别比较最大值,较大值加入目标数组队尾,同时移动较大值指针继续比较
  • 先找到负值和正值的分界点, 相当于找到了平方后的最小值, 然后向两边不断进行遍历
    def sortedSquares1(self, nums):
        """
        定睛一看,时间复杂度不满足要求。
        看思路:
        1.双指针
        2.先找到负值和正值的分界点, 相当于找到了平方后的最小值, 然后向两边不断进行遍历,多找分界点多用了一层循环
        """
        result = [0]*len(nums)
        fir, end, size = 0, len(nums) - 1, len(nums) - 1
        while fir <= end:
            if nums[fir]**2 > nums[end]**2:
                result[size] = nums[fir]**2
                fir += 1
            else:
                result[size] = nums[end] ** 2
                end -= 1
            size -= 1

        return result

代码

class Solution:
    """
    给你一个按 非递减顺序 排序的整数数组 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]
    """
    def sortedSquares(self, nums):
        """
        第一遍,凭第一感觉解
        """
        for i in range(len(nums)):
            nums[i] = nums[i]**2
        nums.sort()
        return nums

    def sortedSquares1(self, nums):
        """
        定睛一看,时间复杂度不满足要求。
        看思路:
        1.双指针
        2.先找到负值和正值的分界点, 相当于找到了平方后的最小值, 然后向两边不断进行遍历,多找分界点多用了一层循环
        """
        result = [0]*len(nums)
        fir, end, size = 0, len(nums) - 1, len(nums) - 1
        while fir <= end:
            if nums[fir]**2 > nums[end]**2:
                result[size] = nums[fir]**2
                fir += 1
            else:
                result[size] = nums[end] ** 2
                end -= 1
            size -= 1

        return result


if __name__ == '__main__':
    test = Solution()
    nums = [[-4, -1, 0, 3, 10], [-7, -3, 2, 3, 11]]
    for tem in nums:
        print(test.sortedSquares1(tem))

想不到第一种方法反而更好些。。。。

第二题

给定一个含有 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

思路

  • 变长滑动窗口,累加和 sum<target时,右指针右滑,逐个加入新元素并累加计算
  • 当累加和sum>target时,计算窗口长度,左指针右移,剔除窗口最左边元素,重复第一步,开始计算新窗口
  • 循环条件取left<len(nums),因为当right=len(nums)时,若sum>target,left右移仍可能存在其它满足条件的解
  • 若right移到最右边时sum<target,结束查找,因为没有新元素加入,sum无法在增大
  • right指向右窗口的下一位,那 right-left刚好为窗口长度

代码

class Solution:
    """
    给定一个含有 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
    """

    def minSubArrayLen(self, target, nums):
        """
        滑动窗口:定长和可变长两类,本题使用可变长
        """
        left, right = 0, 0
        minlen = len(nums) + 1
        list_sum = 0
        while left < len(nums):
            if list_sum < target:
                # 这个判断放在外层不管是开头还是结尾都会导致少算一次,left +1 == len(nums)后,还需进入下一次循环做一次入队后的大小判断
                if right == len(nums):
                    break
                list_sum += nums[right]
                right += 1
            else:
                # 满足条件更新最小值
                minlen = min(minlen, right-left)

                # 剔除最左边元素
                list_sum -= nums[left]
                left += 1

        return minlen if minlen < len(nums) + 1 else 0


if __name__ == '__main__':
    test = Solution()
    nums = [[2, 3, 1, 2, 4, 3], [1, 4, 4], [1, 1, 1, 1, 1, 1, 1, 1]]
    target = [7, 4, 11]
    for i in range(len(nums)):
        print(test.minSubArrayLen(target[i], nums[i]))

第三题

思路

就像是重回到高中做不出最后一道数学大题的迷茫和无助。。。。第一遍反复看别人的思路,每次循环结束记得更新边界值

代码

class Solution:
    """
    给定一个含有 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
    """

    def minSubArrayLen(self, target, nums):
        """
        滑动窗口:定长和可变长两类,本题使用可变长
        """
        left, right = 0, 0
        minlen = len(nums) + 1
        list_sum = 0
        while left < len(nums):
            if list_sum < target:
                # 这个判断放在外层不管是开头还是结尾都会导致少算一次,left +1 == len(nums)后,还需进入下一次循环做一次入队后的大小判断
                if right == len(nums):
                    break
                list_sum += nums[right]
                right += 1
            else:
                # 满足条件更新最小值
                minlen = min(minlen, right-left)

                # 剔除最左边元素
                list_sum -= nums[left]
                left += 1

        return minlen if minlen < len(nums) + 1 else 0


if __name__ == '__main__':
    test = Solution()
    nums = [[2, 3, 1, 2, 4, 3], [1, 4, 4], [1, 1, 1, 1, 1, 1, 1, 1]]
    target = [7, 4, 11]
    for i in range(len(nums)):
        print(test.minSubArrayLen(target[i], nums[i]))

 

总结

只有十分努力,才能看起来毫不费力。。。。我现在就很费力

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值