Day01 代码随想录刷题

Day01 代码随想录刷题

知识点:二分查找、双指针

一、LeetCode704.二分查找

1.解题思路

二分查找首先要明确区间,根据区间不同有两种常用方法,第一种方法是左闭右闭[],第二种方法是左闭右开[)

2.代码实现

2.1 方法一:左闭右闭

因为左闭右闭,两侧的数据可能有效,当计算mid后,若mid所指的nums[mid]不是目标值target,则代表mid的数据nums[mid]无效,不能出现在两侧,所以需要对其进行加一或者减一的操作

返回值存在三种情况:

不存在target,R = L - 1,LR会出现反向超越情况

存在target,在中间

存在target,在两侧,R = L

# way 1 []
def lower_bound(nums, target):
    l, r = 0, len(nums) - 1
    while l <= r:
        mid = l + (r - l)//2
        if nums[mid] > target:
            r = mid - 1
        elif nums[mid] < target:
            l = mid + 1
        else:
            return mid
    return -1

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        return lower_bound(nums, target)

2.2 方法二:左闭右开

因为左闭右开,右侧的数据无效,左侧的数据可能有效,当计算mid后,若mid所指的nums[mid]不是目标值target,则代表mid的数据nums[mid]无效,故不能出现在左侧但可以出现在右侧,所以只有在左侧更新时需要加一,右侧更新不需要减一的操作。

返回值存在三种情况:

不存在target,R = L,LR会出现相等情况

存在target,在中间

存在target,在左侧,R = L + 1

# way 2 [)
def lower_bound2(nums, target):
    l,r = 0,len(nums)
    while l < r:
        mid = l + (r - l)//2
        if nums[mid] > target:
            r = mid
        elif nums[mid] < target:
            l = mid + 1
        else: 
            return mid
    return -1 

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        return lower_bound2(nums, target)

二、LeetCode027.移除元素

1.解题思路

使用快慢指针,快指针j用来遍历数组的每个元素,慢指针i作为下标来更新数组。

2.代码实现

关键在于当快指针j指向的值为要保留的数(!=val)时,将其值更新到慢指针作为下标的数组中nums[i]

数组元素无法被删除,只能被覆盖

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        i = 0
        j = 0
        # # while循环法
        # while j < len(nums):
        #     if nums[j] != val:
        #         nums[i] = nums[j]
        #         i += 1
        #     j += 1

        # return i

        # for循环法
        for j in range(0,len(nums)):
            if nums[j] != val:
                nums[i] = nums[j]
                i+= 1
            j += 1
        return i

三、LeetCode034.在排序数组中查找元素的第一个和最后一个位置

1.解题思路

要找targetnums数组中的左右边界,无非存在 3 种情况:

targetnums列表中存在target

targetnums列表中不存在target

target < nums[0]或者target > nums[n-1]

后2种情况可以通过以下代码排除:

if len(nums) == 0 or nums[0] > target or nums[-1] < target:
    return [-1,-1]

只剩第一种情况,我们需要利用两次二分法来确定左右边界,确定边界的二分法与普通二分法不同,如确定左边界:

nums[mid] == target时,程序不返回mid而是继续将区间向左压缩,所以是right = mid - 1

相反,确定右边界时,当nums[mid] == target时,执行right = mid + 1

这么做的原因是当找到target时不一定是最左或者最右的target

2.代码实现

class Solution:
    # 二分法
    def leftMargin(self,nums,target):
        l, r = 0, len(nums) - 1
        while l <= r:
            mid = l + (r - l)//2
            if nums[mid] < target:
                l = mid + 1
            else:
                r = mid - 1
        if nums[l] == target:
            return l
        else:
            return -1

    def rightMargin(self,nums,target):
        l, r = 0, len(nums) - 1
        while l <= r:
            mid = l + (r - l)//2
            if nums[mid] <= target:
                l = mid + 1
            else:
                r = mid - 1
        if nums[r] == target:
            return r
        else:
            return -1


    def searchRange(self, nums: List[int], target: int) -> List[int]:
 
        # # 暴力解法
        # l = 0
        # r = len(nums) - 1
        # while l < r and (nums[l]!=target or nums[r]!=target):
        #     if nums[l] != target:
        #         l += 1
        #     if nums[r] != target:
        #         r -= 1
        # if l > r:
        #     return [-1,-1]
        # elif l == r:
        #     if nums[l] == target:
        #         return [l,r]
        #     else:
        #         return [-1,-1]
        # return [l,r]


        # 二分法
        if len(nums) == 0 or nums[0] > target or nums[-1] < target:
            return [-1,-1]
        return[self.leftMargin(nums,target),self.rightMargin(nums,target)]

四、LeetCode035.搜索插入位置

1.解题思路

还是二分法,while 循环的条件是left <= right

1.1 当数组中有值为target的元素时,按照普通的二分法,找到该值的索引后返回即可;

1.2 当数组中没有值为target的元素时,最后一次循环搜寻区间可能为一个或两个元素,即right = leftright = left + 1,这两种情况时都有mid = left

如果最后一次循环时mid所在位置的值大,即nums[mid] > target,则right = mid - 1结束循环,不影响left,且left的位置就是要插入的位置;

如果最后一次循环时mid所在位置的值小,即nums[mid] < target,则left = mid + 1结束循环,此时更新后的left的位置就是要插入的位置;

综上,若数组内没有值为target的元素,最后都只需要返回left的索引。

2.代码实现

只需要将普通二分法最后的return -1改为return left即可

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        # # 暴力解法
        # i = 0
        # j = 0
        # for j in range(0,len(nums)):
        #     if nums[j] >= target:
        #         return j
        #     j += 1
        # return j 

        # 二分法
        l = 0
        r = len(nums) - 1
        while l <= r:
            mid = l + (r -l)//2
            if nums[mid] < target:
                l = mid + 1
            elif nums[mid] > target:
                r = mid - 1
            else:
                 return mid
        return l
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值