算法入门刷题二十天(1/20)!

博主分享了备战秋招的算法学习计划,每天练习力扣题目,详解了三种不同算法:线性搜索、二分查找以及寻找错误版本的方法。对于二分查找的实现,强调了防止溢出的计算方式以及优化细节。同时,提出了搜索插入位置问题的解决方案。文章适合算法初学者,探讨了如何在O(logn)的时间复杂度内解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天开始正式备战明年秋招,那算法必不可少,所以从今天开始每天力扣两三道题,有兴趣的可以一起探讨!

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

思路一:比较简单,首先想到的就是遍历数组和目标值进行比较,相等就返回下标值!代码如下:

class Solution {
    public int search(int[] nums, int target) {
       for(int i=0;i<nums.length;i++){
           if(nums[i]==target){
               return i;
           }
       }
       return -1;
    }
}

思路二:为了提高效率,采用二分法比较值,时间复杂度就低了许多!

 public int search(int[] nums, int target) {
        int left=0;//左下标
        int mid;//中间值
        int right=nums.length-1;//右下标
        while(left<=right){//确定还有元素
            mid=(left+right)/2;
            if(nums[mid]==target){//二分出来的值相等就可以返回
                return mid;
            }else if (nums[mid]<target){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
       return -1;
    }
}

- 第二题:有n个版本,找出第一个错误版本!例如【######】找出第一个#的位置!*
解题思路:将左右边界分别初始化为 1 和 n,其中 n 是给定的版本数量。设定左右边界之后,每次我们都依据左右边界找到其中间的版本,检查其是否为正确版本。如果该版本为正确版本,那么第一个错误的版本必然位于该版本的右侧,我们缩紧左边界;否则第一个错误的版本必然位于该版本及该版本的左侧,我们缩紧右边界。
这样我们每判断一次都可以缩紧一次边界,而每次缩紧时两边界距离将变为原来的一半,因此我们至多只需要缩紧 O(\log n)O(logn) 次。

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        int low=1;
        int right=n;
        while(low<right){
            int mid=low + (right - low)/2;//防止计算溢出
            if(isBadVersion(mid)){
                right=mid;
            }else{
                low=mid+1;
            }
        }
      return low;  
    }
}

这个容易理解,当low=right的时候就有结果了!!可以动手尝试一下就知道了,还有一个地方比较难理解的就是:mid=low+(right-low)/2为啥不是(low+right)/2:
比如(9+8)/2=8和8+(9-1)/2还是有很大区别的,第一个式子数值比较大,转换成第二种后就避免了这种情况!!!

- 第三题:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法

解答:

class Solution {
    public int searchInsert(int[] nums, int target) {
        int lo=0;
        int mi;
        int hi=nums.length-1;
        while(lo<=hi){//这里一定要有等号,用于判断最后一轮的目标值到底是在左边还是右边
            mi=lo+(hi-lo)/2;//防止溢出
            if(nums[mi]==target){
                return mi;
            }else if(nums[mi]<target){
                lo=mi+1;
            }else{
                hi=mi-1;
            }
        }      
    return hi+1;
    }
}

有新的解法朋友们可以探讨一下!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值