LeetCode704、二分查找

題目描述

給定一個 n 個元素有序的(升序)整型數組 nums 和一個目標值 target ,寫一個函數搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/binary-search
著作權歸領釦網絡所有。

栗子1

輸入: nums = [-1,0,3,5,9,12], target = 9

輸出: 4

解釋: 9 出現在 nums 中並且下標爲 4

栗子2

輸入: nums = [-1,0,3,5,9,12], target = 2

輸出: -1

解釋: 2 不存在 nums 中因此返回 -1

提示

你可以假設 nums 中的所有元素是不重複的。

n 將在 [1, 10000]之間。

nums 的每個元素都將在 [-9999, 9999]之間。

思路

題目直接以二分查找命名,解題方案不言而喻。提示中說到所有元素不重複,所以最基本的二分查找就可以了。可以選擇遞歸的方式或非遞歸的方式。這裏我選擇了遞歸,如果你想換一種方式,可以思考如何去實現。

又到了老生常談的問題了,二分查找需要注意的幾個地方。

  1. 查找的條件;
  2. mid的寫法;
  3. mid+1和mid-1。

1、我們查找的區間是整個數組,下標0開始,下標nums.length - 1結束。這是我選擇的邊界,只要在這個閉區間[0,nums.length - 1],即low<=high,就去執行程序。你可能會問爲什麼會有等於的情況?
把數字帶進去就懂了[6,6],這時候區間還有一個6需要比較;如果沒有等號就是[6,6),會直接把6漏掉。

2、mid=(low+high)/2;這種方式應該都會理解的,但是如果low和high比較大的話,兩者之和就有可能會溢出。所以就有了改進,將mid的計算寫成low+(high-low)/2。你以爲這就結束了嗎?並沒有,還可以寫成mid=low+((high-low)>>1)。因爲位運算要比除法更快,不過這樣寫一定要注意優先級。

3、low=mid+1,high=mid-1;這裏有+1和-1,因爲我們最先比較的就是索引爲mid的元素,下次比較就不用再比較它了。而且如果直接寫成 low=mid 或者 high=mid,可能會發生死循環。
比如,當 high=2,low=2 時,如果 a[2]不等於 target,就會導致一直循環不退出。

考慮了這些問題再寫代碼就會大大提高勝率了。你的代碼可能和我的不一樣,沒關係,條條大路通羅馬,而且每個人的想法都是不一樣的。只要是對的就可以。

如果有什麼錯誤或者問題,歡迎評論,我們一起探討,一起進步。

代碼

private int searchRecursive(int[] a, int low, int high, int target) {
    if (low > high) {
        return -1;
    }
    int mid = low + ((high - low) >> 1);
    if (a[mid] == target) {
        return mid;
    } else if (a[mid] > target) {
        return searchRecursive(a, low, mid - 1, target);
    } else {
        return searchRecursive(a, mid + 1, high, target);
    }
}

public int search(int[] nums, int target) {
    return searchRecursive(nums, 0, nums.length - 1, target);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章