X6-2、java數(shù)據(jù)結(jié)構(gòu)---二分查找算法【2020-12-22】

總目錄:地址如下看總綱

http://www.lxweimin.com/p/929ca9e209e8

1、介紹【前提有序】

二分查找又稱折半查找,既從中間數(shù)開始找,然后根據(jù)比較結(jié)果,選擇需要折半的一邊出發(fā),
再次折半,以此類推找出元素

2、設計思路(單數(shù))

  1. 、確定當前數(shù)組的下標 mid = (left + right)/2;
  2. 、其次讓需要查找的數(shù) findVal 和 arr[mid] 比較
    (1) findVal > arr[mid] 說明要查找的數(shù)在 mid 右邊,因此向右遞歸查找
    (2) findVal < arr[mid] 說明要查找的數(shù)在 mid 左邊,因此向左遞歸查找
    (3) findVal = arr[mid] 說明找到,既返回
  3. 、需要注意何時結(jié)束遞歸?
    (1)找到就結(jié)束
    (2)遞歸完整個數(shù)組,仍然沒有找到 findVal,也需要結(jié)束遞歸 ,當 left > rigth 就是結(jié)束遞歸的條件

3、代碼(單數(shù)版):只返回一個

/**
     * 二分查找(單數(shù)版)
     * 
     * @param arr     原始數(shù)組
     * @param left    左邊索引
     * @param right   右邊索引
     * @param findVal 查找的值
     * @return
     */
    public static int binarySearch(int[] arr, int left, int right, int findVal) {

        // 當 left > right 時候,說明已經(jīng)遞歸完畢,仍沒有找到
        if (left > right) {
            return -1;
        }

        // 折半,取值
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findVal > midVal) {// 向右遞歸
            return binarySearch(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) {// 向左遞歸
            return binarySearch(arr, left, mid - 1, findVal);
        } else {
            return mid;
        }
    }

4、設計思路(多數(shù))

  1. 、找到第一個匹配的索引值 mid 的時候,不要馬上返回
  2. 、向 mid 索引值 的左邊掃描,將所有與 findVal 相等的元素 的下標 索引返回
  3. 、向 mid 索引值 的右邊掃描,將所有與 findVal 相等的元素 的下標 索引返回

5、代碼(多數(shù)版):找到幾個返回幾個

    /**
     * 二分查找(多數(shù)版)
     * 
     * @param arr     原始數(shù)組
     * @param left    左邊索引
     * @param right   右邊索引
     * @param findVal 查找的值
     * @return
     */
    public static List<Integer> binarySearchS(int[] arr, int left, int right, int findVal) {

        // 當 left > right 時,說明已經(jīng)遞歸完畢,仍沒有找到
        if (left > right) {
            return new ArrayList<Integer>();
        }

        // 折半取值
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findVal > midVal) {
            // 右遞歸
            return binarySearchS(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) {
            // 左遞歸
            return binarySearchS(arr, left, mid - 1, findVal);
        } else {
            // ****************以下代碼才是和簡單版的區(qū)別所在,以上都一樣*******
            // 1、找到第一個匹配的索引值 mid 的時候,不要馬上返回
            // 用于接受結(jié)果
            List<Integer> resIndexList = new ArrayList();

            // 2、向 mid 索引值 的左邊掃描,將所有與 findVal 相等的元素 的下標 索引返回
            int temp = mid - 1;// 左遞歸起始索引
            while (true) {
                if (temp < 0 || arr[temp] != findVal) {
                    break;// 不滿足,退出(固二分為有序,左邊的第一個不相同,再找也是不同)
                } else {
                    // 加入,左移(再找)
                    resIndexList.add(temp);
                    temp -= 1;
                }
            }
            resIndexList.add(mid);

            // 3、向 mid 索引值 的右邊掃描,將所有與 findVal 相等的元素 的下標 索引返回
            temp = mid + 1;
            while (true) {
                if (temp > arr.length - 1 || arr[temp] != findVal) {
                    break;
                } else {
                    resIndexList.add(temp);
                    temp += 1;
                }
            }
            return resIndexList;
        }
    }

6、最終完整代碼

/**
 * title: 二分查找(單,多數(shù)版)
 * @author 阿K
 * 2020年12月22日 下午9:56:17 
 */
public class BinarySearch {

    public static void main(String[] args) {
        int arr[] = { 1, 8, 10, 89, 1000, 1000, 1234 };

        int findVal = 1000;
        System.out.println(binarySearch(arr, 0, arr.length - 1, findVal));
        System.out.println(binarySearchS(arr, 0, arr.length - 1, findVal));
    }

    /**
     * 二分查找(單數(shù)版)
     * 
     * @param arr     原始數(shù)組
     * @param left    左邊索引
     * @param right   右邊索引
     * @param findVal 查找的值
     * @return
     */
    public static int binarySearch(int[] arr, int left, int right, int findVal) {

        // 當 left > right 時候,說明已經(jīng)遞歸完畢,仍沒有找到
        if (left > right) {
            return -1;
        }

        // 折半,取值
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findVal > midVal) {// 向右遞歸
            return binarySearch(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) {// 向左遞歸
            return binarySearch(arr, left, mid - 1, findVal);
        } else {
            return mid;
        }
    }

    /**
     * 二分查找(多數(shù)版)
     * 
     * @param arr     原始數(shù)組
     * @param left    左邊索引
     * @param right   右邊索引
     * @param findVal 查找的值
     * @return
     */
    public static List<Integer> binarySearchS(int[] arr, int left, int right, int findVal) {

        // 當 left > right 時,說明已經(jīng)遞歸完畢,仍沒有找到
        if (left > right) {
            return new ArrayList<Integer>();
        }

        // 折半取值
        int mid = (left + right) / 2;
        int midVal = arr[mid];

        if (findVal > midVal) {
            // 右遞歸
            return binarySearchS(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) {
            // 左遞歸
            return binarySearchS(arr, left, mid - 1, findVal);
        } else {
            // ****************以下代碼才是和簡單版的區(qū)別所在,以上都一樣*******
            // 1、找到第一個匹配的索引值 mid 的時候,不要馬上返回
            // 用于接受結(jié)果
            List<Integer> resIndexList = new ArrayList();

            // 2、向 mid 索引值 的左邊掃描,將所有與 findVal 相等的元素 的下標 索引返回
            int temp = mid - 1;// 左遞歸起始索引
            while (true) {
                if (temp < 0 || arr[temp] != findVal) {
                    break;// 不滿足,退出(固二分為有序,左邊的第一個不相同,再找也是不同)
                } else {
                    // 加入,左移(再找)
                    resIndexList.add(temp);
                    temp -= 1;
                }
            }
            resIndexList.add(mid);

            // 3、向 mid 索引值 的右邊掃描,將所有與 findVal 相等的元素 的下標 索引返回
            temp = mid + 1;
            while (true) {
                if (temp > arr.length - 1 || arr[temp] != findVal) {
                    break;
                } else {
                    resIndexList.add(temp);
                    temp += 1;
                }
            }
            return resIndexList;
        }
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內(nèi)容