代码随想录刷题Day2 -- LC34:在排序数组中查找元素的第一个和最后一个位置(index)|LC977: 有序数组的平方 | LC209: 长度最小的子数组

LC 34: Find 1st and Last Position of Element in Sorted Array 

题目要求:在排序过(非递减)的array - nums中找出target value 的start index 和 end index, 且必须用O(logN) 的二分查找法做出

思路:双指针的红蓝染色法

1. 假设target 在[L, R] 中, 使用while (L <= R) loop, 让左指针一直向右移动, 直到 right < left pointer 时可以知道:左边红色区域的数字肯定是 < target ; 右边蓝色区域的数字肯定是 >= target的

class Solution:
    def lower_bound(self, nums, target) -> int:
        l, r = 0, len(nums) - 1

        while (l <= r):
            mid = (l + r) // 2
            if (target > nums[mid]): # 为什么这个要写到前面: 因为我们想让left 一直往右移
                l = mid + 1
            else: 
                r = mid - 1
        return l # 然后当r < l 的时候, 我们确保r及左边的数是小于target的, l及右边的数是大于等于target的, l是右边区域最小的

    def searchRange(self, nums: List[int], target: int) -> List[int]:
        # 假设target在 [L,R]中
        start_idx = self.lower_bound(nums, target)

        # 如果start_idx = nums的长度 或者直到l被挪到最右边的上面的数值也不等于target,
        # 那就说明整个array中没有target
        if(start_idx == len(nums) or nums[start_idx] != target):
            return [-1,-1]

        # target已经找到了,继续看target的下一个数, 也就是target+1,的前面一个index        
        end_idx = self.lower_bound(nums, target + 1) - 1

        return [start_idx, end_idx]

LC977: 有序数组的平方 

  • 双指针: i = 0, j = nums.size - 1
  • 设置新的array = ret, 指针为k,k = nums.size - 1, 从后往前走, 因为题目要求最大的在最后
  • while (i <= j) , 比较nums[i]的方大还是nums[j]的方大, 新的array, ret[k] = 更大的数的方
  • 注意 i和j的增减, k一直都-=1,因为在向左边移动
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        ret = [float('-inf')] * len(nums) #建立新的数组, 大小 = nums.size
        i = 0
        j = len(nums) - 1
        k = len(nums) - 1 # 因为新的数组是由大到小, 最后一位是最大的, 所以k是size - 1

        while (i <= j): #当 i <= j 时,i可以移动到array中的最后一位, 所以i = j
            if (nums[i]**2 > nums[j]**2): #如果nums[i]的平方大, 从ret[k] 也就是从ret的最后一位开始, ret[k] = nums【i】的方
                ret[k] = nums[i]**2
                i += 1
                
            else:
                ret[k] = nums[j]**2 # 不然ret【k】就是nums【j】的方
                j -= 1
            k -= 1 # 因为题目要最大的方后面, k从后往前走的
        
        return ret

LC209: 长度最小的子数组

题目要求: 找出subLen最短的subarray, 使得subarray的和 >= target value

思路: sliding window

1. i和j都从idx = 0开始, j在前走, 更新sum += nums [ j ]

2. 当得到的sum 一直都大于或等于target的时候, 算出每次的subLen, 更新最短的subLen(这里是ret), 让 idx i 向右挪动,看右边的会不会有新的组合满足要求

3. 如果直到 j 走到最后, ret都没有更新,那说明array中没有满足要求的, return 0 

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        # 这道题是典型的sliding window题目
        # 我们设置i和j两个指针, 从头开始向右走,j走在前面nums[j]一直相加
        i = 0
        j = 0 
        sum = 0 # sum = nums【j】一直相加的和
        ret = float('Inf') # ret为最后return的最短的subarray的长度 subLen = j-i+1


        # for loop 中得到nums[j]的和
        for j in range(len(nums)):
            sum += nums[j]
            while(sum >= target):
                subLen = j - i + 1 # sliding window的长度,j和i之间的距离
                ret = min(ret, subLen) # 求最短长度
                # 为什么i要向右边移动
                # 因为我们想subLen的长度为最小,所以当我们发现目前sum已经 > 或 = target了,就不考虑目前的nums[i]了
                sum -= nums[i]
                i += 1 # 我们得让i向右边挪,看右边会不会有新的组合满足要求 

        if(ret == float('Inf')): # 如果ret还是之前的Inf没变过, 说明array中没有>= target的, return 0
            return 0
        else: 
            return ret 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值