代码随想录算法训练营第一天 | 704. 二分查找、27. 移除元素

704.二分查找

文档讲解:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
视频讲解:https://www.bilibili.com/video/BV1fA4y1o715
状态:第4、5遍做了,思路较为清晰。本次顺带完成了相关题目。

思路

二分法前提条件:元素顺序排列;无重复。
主要知识点:循环不变量。
关于区间的界定:

  1. 如果假设target在闭区间[left,right]内,那么left<=right是有意义的。如果target<nums[mid],那么right的更新为mid-1.因为nums[mid]一定不是target。
  2. 如果假设target在左闭右开区间[left,right),那么left<=right没有意义,等号取不到。此时如果target<nums[mid],那么right的更新为mid.因为如果更新为mid-1,那mid-1这个值为区间的上限,取不到,就会少考虑这种可能。

代码:

版本一:左右都是闭区间

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        left = 0
        right = len(nums)-1
        while left <= right:
            mid = left + (right - left)//2 # 为了防止溢出
            if nums[mid] > target:
                right = mid - 1
            elif nums[mid] < target:
                left = mid + 1
            else:
                return mid
        return -1

版本二:左闭右开

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        left = 0
        right = len(nums)
        while left < right:
            mid = left+(right - left)//2 # 为了防止溢出
            if nums[mid] > target:
                right = mid
            elif nums[mid] < target:
                left = mid + 1
            else:
                return mid
        return -1

35.搜索插入位置(二分查找相关题目)

题目链接:https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/
状态:思路较为明确,为了复习java,本次使用Java完成。

思路

本题相较于二分查找,要求变为了找不到的话就返回插入位置。考虑到在找不到的情形下,最终left指针和right指针总会经历一个重叠,交叉的过程。也就是说在最后一次进入循环更新完mid后,存在以下情形:left=mid=right。那么我们分析:当target大于nums[mid]时,应插入的位置为right+1,也就是更新后的left;当target小于nums[mid]时,应插入的位置为left(将原本的数组向后挤一个位置)。因此,最后返回left即可。

代码:

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0;
        int right = nums.length-1;
        int mid = 0;
        while(left<=right){
            mid = left+(right-left)/2;
            if(target<nums[mid]){
                right = mid-1;
            }
            else if(target>nums[mid]){
                left = mid+1;
            }
            else{
                return mid;
            }
        }
        return left;
    }
}

34.搜索插入位置(二分查找相关题目)

题目链接:https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/
状态:思路较为明确,为了复习java,本次使用Java完成。代码整体不够精炼,Java使用熟练度较低,多多练习。

思路

本题在二分查找的基础上,增加了窗口滑动,确定相同元素的范围区间,注意不要数组越界就好。

代码:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int left = 0;
        int right = nums.length-1;
        int ans = -1;
        int[] ansArr = new int[]{-1,-1};
        while(left <= right){
            int mid = left + (right - left) / 2;
            if(nums[mid] > target){
                right = mid - 1;
            }
            else if(nums[mid] < target){
                left = mid + 1;
            }
            else{
                ans = mid;
                break;
            }
        }
        if(ans==-1){
            return ansArr;
        }
        for(int i = ans; i>=0;i--){
            if(nums[i]==target){
                ansArr[0]=i;
            }
            else{
                break;
            }
        }
        for(int i = ans;i<nums.length;i++){
            if(nums[i]==target){
                ansArr[1] = i;
            }
            else{
                break;
            }
        }
        return ansArr;
    }
}

27.移除元素

文档讲解:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html
视频讲解:https://www.bilibili.com/video/BV12A4y1Z7LP
状态:第4、5遍做了,思路较为清晰。

思路

主要思路是双指针:

  1. 两个指针,分别为快指针和慢指针。快指针负责遍历数组,判断情况,慢指针负责维护更新数组。

代码:

class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        fast = 0
        slow = 0
        for fast in range(len(nums)):
            if nums[fast]!=val:
                nums[slow]=nums[fast]
                slow+=1
            fast+=1
        return slow
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值