【LeetCode】二分法相关

本文精选了五道LeetCode上的二分法经典题目,包括二分搜索、搜索插入位置、X的平方根、有效的完全平方数及Pow(x,n),详细解析了每道题目的解题思路与代码实现,为读者提供了深入理解二分法技巧的机会。

题目一:二分搜索


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

链接:https://leetcode-cn.com/problems/binary-search/

思路:


这个是最常规的二分法的问题,不断地缩小搜索范围来找到最终的值。以下代码可以作为此类题目的模板。

代码:


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

题目二:搜索插入位置


给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

链接:https://leetcode-cn.com/problems/search-insert-position/

思路:


思路基本就是二分查找的思路,差别就在于如果没有找到目标值,返回的是插入的位置。

代码:


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

题目三:X的平方根


实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

链接:https://leetcode-cn.com/problems/sqrtx/

思路:


X的平方根一定在0~X之间,我们可以采用二分法来解决这个问题。注意这道题要使用long类型,因为int型的数据平方之后可能超过int型数据的表示范围。具体到代码里,这道题目与前两道题目的不同点在于判定条件。于此类似的问题不同点可以看作是做判断的那一步骤不同,思想大同小异。

还有几点要注意:求中间的数:最好使用mid = (left + right) >>> 1(左中位数)或者mid = (left + right + 1) >>> 1(右中位数),区分左右中位数的原因是在某些情况下,选择默认的左中位数,会进入死循环,因此这里要具体情况具体分析。while语句的判定条件:最好使用left < right,因为这样可以在while循环结束后,不用去考虑left和right的情况,基本是left==right的情况,才会跳出循环。

代码:


class Solution {
    public int mySqrt(int x) {
        if(x == 0) {
            return 0;
        }
        long left = 1;
        long right = x;
        
        while(left < right) {
            //进入右中位数
            long mid = (left + right + 1) >>> 1;
            
            long square = mid * mid;
            if(square > x) {
                right = mid - 1;
            } else {
                left = mid;
            }
        }
        return (int)left;
    }
}

题目四:有效的完全平方数


给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 False。

说明:不要使用任何内置的库函数,如  sqrt。

链接:https://leetcode-cn.com/problems/valid-perfect-square/

思路:


思路与上一题基本一致。要注意一点,跳出while循环之后,要对left(right)的数据进行处理,不然会漏掉那个数据。

代码:


class Solution {
    public boolean isPerfectSquare(int num) {
        if(num == 0 || num == 1) {
            return true;
        }
        
        long left = 1;
        long right = num / 2;
        
        while(left < right) {
            long mid = (left + right) >>> 1;
            long square = mid * mid;
            if(square == num) {
                return true;
            } else if(square > num) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        if(left * left == num) {
            return true;
        }
        return false;
    }
}

题目五:Pow(x, n)


实现 pow(xn) ,即计算 x 的 n 次幂函数。

链接:https://leetcode-cn.com/problems/powx-n/

思路:


采用二分递归的思想,2^{n} = (2^{\frac{n}{2}})^{2},不断的计算2^{\frac{n}{2}},使用递归求出结果。

代码:


class Solution {
    public double myPow(double x, int n) {
        if(n == 1) {
            return x;
        }
        if(n == -1) {
            return 1 / x;
        }
        if(n == 0) {
            return 1;
        }
        double temp = myPow(x, n / 2);
        double rest = myPow(x, n % 2);
        double ans = temp * temp * rest;
        return ans;
    }
}

参考资料:


https://www.liwei.party/2019/06/19/leetcode-solution-new/search-insert-position/

后续更新细节。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值