java算法之二分查找

二分查找说人话:

在一个升序的数组里面找到一个想找到的值,一般是返回索引即可。

怎么用二分找?

二分二分就是不断除以二得到猜测值来与目标值进行比较,并且寻找的范围也逐渐折半,直到找到目标值。

看图理解!:

看答案是大还是小来选择左边或者右边的查找范围。

上代码:

package binarySearch;

/**
 * 二分查找基础版本
 * Params: a -待查找的升序数组
 *         target -待查找的目标值
 * Returns: 找到则返回索引
 *          找不到则返回-1
 */
public class BinarySearch {
    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;
    }
}

下面是测试类,还是挺好用的哦!

package binarySearch;

import org.junit.Test;
import org.junit.jupiter.api.DisplayName;

import static binarySearch.BinarySearch.binarySearchBasic;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class TestBinarySearch {
    @Test
    @DisplayName("binarySearchBasic 找到")
    public void test1(){
        int[] a={7,13,21,30,38,44,52,53};
        assertEquals(0,binarySearchBasic(a,7));
        assertEquals(1,binarySearchBasic(a,13));
        assertEquals(2,binarySearchBasic(a,21));
        assertEquals(3,binarySearchBasic(a,30));
        assertEquals(4,binarySearchBasic(a,38));
        assertEquals(5,binarySearchBasic(a,44));
        assertEquals(6,binarySearchBasic(a,52));
        assertEquals(7,binarySearchBasic(a,53));
    }
    @Test
    @DisplayName("binarySearchBasic 没找到")
    public void test2(){
        int[] a={7,13,21,30,38,44,52,53};
        assertEquals(-1,binarySearchBasic(a,0));
        assertEquals(-1,binarySearchBasic(a,9));
        assertEquals(-1,binarySearchBasic(a,22));
        assertEquals(-1,binarySearchBasic(a,55));
    }
}

给个idea代码结构:

改动版效果一样,直到就行没必要用:

书接上回,这次学了二分查找的平衡版,就是时间复杂度更小的版本,相对于基础版本来说。

代码:

//二分查找平衡版  时间复杂度更小
    public static int binarySearch2(int[] a,int target){
        int i=0,j=a.length;
        while(1<j-i){   //这个while循环是为了逐步缩小范围,最后只剩下相等的情况 再比较是否相等
            int m=(i+j)>>>2;    //>>>是无符号   >>是有符号
            if(target<a[m]){
                j=m;
            }else {
                i=m;
            }
        }
        if(a[i]==target){
            return i;
        }else{
            return -1;
        }
    }

思路:

首先右边指针j指向最后一个地方的下一个,即空,在while循环中是为了一步一步缩小范围,直到i和i相等,最后比较最后的值与目标值是否相等来判断是否找到目标值。

有一个有意思的小测试,使用的是java本身自带的二分查找方法:

使用maven创建java项目,在test中进行测试:

@Test
    @DisplayName("binarySearch java版")
    public void test3(){
        int[] a={2,5,8};
        int target=4;
        int i= Arrays.binarySearch(a,target);   //java自带的二分查找,若没找到则返回应该插入的索引的负数再-1
        System.out.println(i);
        if(i<0){    //只要找到了肯定是整数  没找到才是负数
            int insertIndex=Math.abs(i+1);   //插入点索引
            int[] b=new int[a.length+1];
            System.arraycopy(a,0,b,0,insertIndex);
            b[insertIndex]=target;
            //五个参数  数组1 起始索引  数组2  起始索引  复制长度
            System.arraycopy(a,insertIndex,b,insertIndex+1,a.length-insertIndex);
            System.out.println(Arrays.toString(b));
        }
    }

这个测试的内容是:首先a数组的值为2,5,8 然后想要找到4这个值,但是没有,java自带的二分超找如果没有找到目标值,那么就会返回负的目标值如果要插入的下标再-1,我这个是手动把4插入到a数组了。

补充一下还有时间复杂度的知识:

上面是一些常见的时间复杂度,一般说时间复杂度分为大O时间复杂度,Ω时间复杂度,c他时间复杂度,大O时间复杂度是代表复杂度最高的一种,Ω时间复杂度是代表复杂度最低的一种,c他是既有最高时间复杂度也有最低时间复杂度的,即目标算法的时间复杂度介于两者之间。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值