算法Day01-1119刷题:数组–704. 二分查找,27. 移除元素,977. 有序数组的平方,209. 长度最小的子数组

Day01-1119刷题:数组–704. 二分查找,27. 移除元素,977. 有序数组的平方,209. 长度最小的子数组

题目用时
704.二分查找14m51s
27. 移除元素5m54s
977. 有序数组的平方17m12s
209. 长度最小的子数组30m

704.二分查找

[!NOTE]

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果 target 存在返回下标,否则返回 -1

你必须编写一个具有 O(log n) 时间复杂度的算法。

首次写没有注意到循环结束条件,模糊了左闭右闭和左闭右开的区别;其次,将return -1写到了while循环else中,导致出现超时;

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        length = len(nums)
        left,right = 0, length - 1
        while left <= right:
            if target < nums[(left + right)/2]:
                right = (left + right)/2 - 1 
            elif target > nums[(left + right)/2]:
                left = (left + right)/2 + 1
            elif target == nums[(left + right)/2]:
                return (left + right)/2
        return -1

[!TIP]

mid = (left + right)/2来统一表示, 且最好用(left + right) / 2避免溢出

27.移除元素

[!NOTE]

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 k

这题之前在labuladong的双指针技巧中有学到,原地移除限制了不能遍历数组将不等于 val 的值移动到新数组中,也就是说遇到 nums[i] == val 的情况时,我需要直接修改 nums[i] 的值,直接的想法是双循环,外层寻找nums[i] == val ,内层负责更新数组(将所有i以后的前移一位),为了减少一层循环则可以用到快慢指针,将慢指针内的值定为存储非val值,当快指针遇到val时,则跳过将这个值存储到慢指针的前k个区域内

class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        fast, slow = 0, 0
        while fast < len(nums):
            if nums[fast] != val:
                nums[slow] = nums[fast]
                slow += 1
            fast += 1
        nums = nums[:slow]
        return slow

977.有序数组的平方

[!NOTE]

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

最开始想的直接用平方后的结果sort一下就好了,时间复杂度是 O(n + nlogn)

后续考虑到用左右指针的方法,先将数组进行平方,再将左右比较,大的先加进数组,然后缩小再比较,最后用 reverse(),时间复杂度是 O(n + n + n)

最终考虑直接将大的加入到结果数组的末尾(减少reverse的操作)

class Solution(object):
    def sortedSquares(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        # square = [i**2 for i in nums]
        left, right = 0, len(nums) - 1
        sorted_square = [0] * len(nums)
        i = len(nums) - 1
        while left <= right:
            if nums[left]**2 < nums[right]**2:
                sorted_square[i] = nums[right]**2
                right -= 1
                i -= 1
            else:
                sorted_square[i] = nums[left]**2
                left += 1
                i -= 1

        return sorted_square  

209. 长度最小的子数组

[!NOTE]

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

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

想要用滑动窗口解决问题,小了则右边扩大,大了则左边缩小

class Solution(object):
    def minSubArrayLen(self, target, nums):
        """
        :type target: int
        :type nums: List[int]
        :rtype: int
        """
        fast, slow = 0, 0
        min_length = len(nums) + 1
        if sum(nums) < target:
            return 0
        while fast <= len(nums) - 1:
            if sum(nums[slow:fast + 1]) < target:
                fast += 1
            elif sum(nums[slow:fast + 1]) >= target:
                length = fast - slow + 1
                if length < min_length:
                    min_length = length
                slow += 1
        return min_length            
                

这样写是错误的,因为不断在计算sum(nums[slow:fast + 1]),因此优化了一下,用一个数组暂存值的和,再进行加减,这样的话就需要在判断sum>target的时候用上while来进行窗口的持续移动

class Solution:
    def minSubArrayLen(self, s, nums):
        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         

[!TIP]

这题卡了很久,最开始就想到了用滑动窗口解决这个问题,在第一版中由于不断多次的计算sum(nums[slow:fast + 1])而导致超时问题,考虑用数组暂存后又忽略了每次外循环时会重复加上nums[right]的值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值