【数据结构】二分查找5.12

Basic

需求:在有序数组A内,查找值target

如果找到返回索引

如果找不到返回-1


算法描述

前提:给定一个内含n个元素的有序数组A(升序),一个待查找值

设置两个索引:i=0;j=n-1;

如果j>i,查找停止

设置m=floor(i+j/2),floor为向下取整的最小整数

如果target>m,设置i=m+1;

如果traget<m,设置j=m-1;

如果traget=m,找到待查找值。

 

实现

package 二分查找;

public class BinarySearch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
	}
     public static int binarySearchBasic(int[] a,int target) {
    	 int i=0,j=a.length-1; //设置指针初值
    	 while(i<=j) { //范围有内容
    		 int m=(i+j)/2;
    		 if(target<a[m]) {
    			 j=m-1;
    		 }else if(target>a[m]) {
    			 i=m+1;
    		 }else {
    			 return m;
    		 }
    	 }
    	 return -1;
	}

}

问题1:

为什么是i<=j,而不是i<j?

i,j区间内会有未比较的元素,i<=j它们共同指向的元素也可以遍历到。

 

问题2:

(i+j)/2有没有问题?

若数字较大,再次循环:

i=m+1;

m=(i+j)/2;会超出范围变成负数

同一个二进制数,第一位是否是符号位。会使数值展现不同。(Java中会考虑符号位)

可以通过无符号右移来达到除2效果。

 

解决方法:

无符号右移>>>

package 二分查找;

public class BinarySearch {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
	}
     public static int binarySearchBasic(int[] a,int target) {
    	 int i=0,j=a.length-1; //设置指针初值
    	 while(i<=j) { //范围有内容
    		 int m=(i+j)>>>2;
    		 if(target<a[m]) {
    			 j=m-1;
    		 }else if(target>a[m]) {
    			 i=m+1;
    		 }else {
    			 return m;
    		 }
    	 }
    	 return -1;
	}

}

额外应用:

(0+7)/2          3.5     //不需要设置float,可当成整数

(0+7)>>>1    3

 

练习优化过程

Pocess1超出时间限制

class Solution {
    public int searchInsert(int[] nums, int target) {
        int i=0,j=nums.length-1;
        int m=(i+j)>>>1;
        int index=0;
        while(i<=j){
            index++;
        if(target<m){
            j=m-1;
        }else if(m<target){
            i=m+1;
        }else{
           return index;
        }
        }
       
        for(int k=0;k<nums.length;k++){
            while(target>nums[k]){
                index=k+1;
            }
        }
        return index;
       
    }
}

问题分析:

1. 二分查找逻辑错误:比较 target 和 m(中间索引)而不是 nums[m](中间值)。

2. 无限循环:在二分查找部分,没有更新 m的值,导致循环条件永远不变。

3. 错误的索引计算:在二分查找中返回的是 index(循环次数)而不是正确的位置。

4. 不必要的线性搜索:最后的线性搜索部分既不正确也不必要。i就是应该插入的位置。

Process2优化

class Solution {

    public int searchInsert(int[] nums, int target) {

        int i = 0, j = nums.length - 1;

        while (i <= j) {

            int m = (i + j) >>> 1;

            if (nums[m] == target) {

                return m;

            } else if (nums[m] < target) {

                i = m + 1;

            } else {

                j = m - 1;

            }

        }

        return i;

    }

}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值