【java-面试-算法】二分查找及优化

二分查找

步骤:

  1. 有序数组(这是前提,默认)

  2. 创建一个最左变量L,一个最右变量R,中间索引M=(L+R)/2(这里要注意,在java中浮点数取整为向下取整,如(3+2)/2=2,也要和4舍5入区分开),循环执行步骤3

  3. 如果L<=R

    • 如果目标值等于下标为M的值,则返回M

    • 如果目标值大于下标为M的值,则L=M+1

    • 如果目标值小于下标为M的值,则R=M-1

  4. 如果L>R,没找到返回-1

代码:

public class d {
    public static void main(String[] args) {

        int[] num={23,24,26,36,234,453,2357,123456};
        int target=4;
        int i = binTree(num, target);
        System.out.println(i);

    }

    public static int binTree(int[] num,int target){
        int L=0,R=num.length-1;
        while (L<=R){
            int M=(L+R)/2;
            if (target==num[M]){
                return M;
            }else if (target<num[M]){
                R=M-1;
            }else{
                L=M+1;
            }
        }
        return -1;
    }
}
public static void main(String[] args) {
    int a=(Integer.MAX_VALUE+(Integer.MAX_VALUE-1))/2;
    System.out.println(a);
}

输出:

-1

不足:当L和R都特别大时就会存在M值大于int类型的最大值,存在整数溢出。

原因:int 类型和Integer包装类型的取值范围都为-2147483648~2147483647,当int的值大于2147483647或小于-2147483648时就会产生溢出。

方法一

实际需要的值:(2147483646+2147483647)/2=2,147,483,646 

溢出后的值:-1      (L+R)/2
 
中间索引:L+(R-L)/2   --->L+R/2-L/2--->(L+R)/2   (R-L)/2   两数相减值不会溢出
public static void main(String[] args) {
    int a=Integer.MAX_VALUE+(-Integer.MAX_VALU+(Integer.MAX_VALUE-1))/2;
    int b=(Integer.MAX_VALUE+(Integer.MAX_VALUE-1))/2;
    System.out.println(a);
    System.out.println(b);

}

输出:

2147483647
-1

方法二

因为计算机存储数字都是以补码的形式存储的。所以可以通过移位运算来避免溢出。
举个例子,8位带符号的二进制数运算

01111111+01111111=111111110 127+127=-2 (127+127)/2=127

将结果向右移一位:01111111 ------>127 刚好等于我们想要的值

中间索引:M=(L+R)>>>1
public static void main(String[] args) {
    int a=Integer.MAX_VALUE+(-Integer.MAX_VALUE+(Integer.MAX_VALUE-1))/2;
    int b=(Integer.MAX_VALUE+(Integer.MAX_VALUE-1))>>>1;
    System.out.println(a);
    System.out.println(b);

}
2147483647
2147483647
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

B64A-消闲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值