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一行?),嚶嚶嚶

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