Java 手写二分查找算法(找出全部下标),递归与非递归实现

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

你要走二分查找,你首先得支楞起来啊~(数组有序)

一.递归实现

注解基本都有,这里不再详细解释了,我们这个二分查找需要找出所有的元素下标~

package DataStructure.BinarySearch;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class BinarySearchDemoDigui {
    public static void main(String[] args) {
        int arr[]={1,2,3,3,3,4,5,5,6,6,7};
        Arrays.sort(arr);//二分查找要保证数组有序,其实没必要有这一步~~
        System.out.println(get(arr,0,arr.length-1,300));
    }

    public static List get(int arr[],int left,int right,int value){

        int mid=(left+right)/2;
        int midval=arr[mid];

        if(left>right) return new ArrayList();  //结束条件 那左下标都大于右下标了肯定返回了~

        if(value>midval){  //如果我们要找得值是大于中间值的,那它肯定是在中间值右边的,那我们就只用考虑中间值右半部分的
             return get(arr,mid+1,right,value);
        }else if(value<midval){ //如果我们要找得值是小于中间值的,那它肯定是在中间值左边的,那我们就只用考虑中间值左半部分的
             return get(arr,left,mid-1,value);
        }else {
            List<Integer> list=new ArrayList(); //这里我们优化一下算法,这里返回所有与查找值相同的数组下标,用list收集起来

            int temp=mid-1; //首先在这个条件里的值肯定是等于要查找数的值,那首先数组是有序的,那我们只需要从左或者从右判断是否有与相同值即可
            while(true){
                if(temp<0||arr[temp]!=value){  //结束条件,下同
                    break;
                }
                list.add(temp);  //符合条件就加到list里
                temp-=1;        // 继续向左查找
            }

            list.add(mid);  //别忘了把中间值加进去

            temp=mid+1;  //继续向右查找
            while(true){
                if(temp>arr.length-1||arr[temp]!=value){
                    break;
                }
                list.add(temp);
                temp+=1;
            }
            return list;
        }

    }
}

二. 非递归实现

package DataStructure.BinarySearch;

import java.util.ArrayList;
import java.util.List;

/**
 * 二分查找非递归
 */
public class BinarySearchDemo {

    public static void main(String[] args) {
        int arr[]={1,2,3,4,5,6,7,7,7};
        System.out.println(getIndex(arr, 7));
    }

    public static List<Integer> getIndex(int[] arr,int val){
        int left=0;  
        int right=arr.length-1;   
        List<Integer> list=new ArrayList<>();
        while(left<=right){  //结束条件肯定是left>right
            int mid=(left+right)/2; //那我们肯定每次都需要计算mid值啊
            if(val==arr[mid]){  //这里我判断了如果查到了,那接下来一系列操作与递归写的相同(就是向左向右查找相同值加到list中)
              int temp=mid-1;
              while(true){
                 if(temp<0||arr[temp]!=val)   {
                     break;
                 }
                 list.add(temp);
                 temp-=1;
              }
              list.add(mid);
              temp=mid+1;
              while(true){
                  if(temp>arr.length-1||arr[temp]!=val)   {
                      break;
                  }
                  list.add(temp);
                  temp+=1;
              }
              return list;
            }else if(val<arr[mid]){
                right=mid-1;
            }else {
                left=mid+1;
            }
        }
        return new ArrayList<>();
    }
}

大佬们,把你们的优秀代码展示出来啊(例如Python一行?),嘤嘤嘤

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章