神級算法——二分天下

二分查找

二分查找也稱折半查找(Binary Search),它是一種效率較高得查找方法。一般都是要求線性表有序,然後二分查找的時間複雜度爲O(logN)。

不一樣的二分

如果數組無序,難道就不能用二分查找了嗎?答案是否定的,即使一個數組無序,也可以用二分查找來找。下面我就用兩個例子來給你們上一課(膨脹了我,哈哈~~~)

例子1(旋轉數組):

把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。

思路:

即使數組無序,但是我們還是可以使用二分查找來找出最小值。因爲旋轉數組部分有序,利用二分查找還是很容易查找到最小值

代碼:

public class Solution {
    public int minNumberInRotateArray(int [] array) {
        int low = 0 ; 
        int high = array.length - 1;  
        while(low < high){
            int mid = low + (high - low) / 2;       
            if(array[mid] > array[high]){
                low = mid + 1;
            }else if(array[mid] == array[high]) {
				high--;
			}else{
                high = mid;
            }  
        }
        return array[low];
    }
}

通過:

在這裏插入圖片描述

可能有人會覺得,即使無序可以使用二分查找,但是你這個旋轉數組也是部分有序,所以可以使用二分查找。接下來我再講解一道題來證明給你看——查找局部最小值。

例子2(查找局部最小值)

定義局部最小的概念。arr數組長度爲1時,arr[0]是局部最小。arr的長度爲N(N>1)時,如果arr[0]<arr[1],那麼arr[0]是局部最小;如果arr[N-1]<arr[N-2],那麼arr[N-1]是局部最小;如果0<i<N-1,既有arr[i]<arr[i-1],又有arr[i]<arr[i+1],那麼arr[i]是局部最小。
給定無序數組arr,已知arr中任意兩個相鄰的數都不相等。寫一個函數,只需返回arr中任意一個局部最小出現的位置即可。

思路:

  • 先查找arr[0]和arr[N-1],即第一個數和最後一個數是不是局部最小,如果是,直接返回這個數即可。
  • 如果arr[0]>arr[1],arr[N-1]>arr[N-2],那麼此時的情況就是這樣的:
    在這裏插入圖片描述

代碼:

/**
 * @author god-jiang
 * @date 2020/1/14  15:19
 */
public class FindOneLessValueIndex {

    public static int getLessIndex(int[] arr) {
        //如果不存在直接return -1
        if (arr == null || arr.length == 0) {
            return -1;
        }
        //先看arr[0]和arr[N-1]是不是局部最小,是的話直接返回即可
        if (arr.length == 1 || arr[0] < arr[1]) {
            return 0;
        }
        if (arr[arr.length - 1] < arr[arr.length - 2]) {
            return arr.length - 1;
        }

        //然後中間部分使用二分
        int left = 1;
        int right = arr.length - 2;
        int mid = 0;
        while (left < right) {
            mid = left + (right - left) / 2;
            if (arr[mid] > arr[mid - 1]) {
                right = mid - 1;
            } else if (arr[mid] > arr[mid + 1]) {
                left = mid + 1;
            } else {
                return mid;
            }
        }
        return left;
    }

    public static void printArray(int[] arr) {
        for (int i = 0; i != arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int[] arr = {6, 5, 3, 4, 6, 7, 8};
        printArray(arr);
        int index = getLessIndex(arr);
        System.out.println("index: " + index + ", value: " + arr[index]);

    }
}

運行結果:

在這裏插入圖片描述

總結

看了上面的兩個例子,是不是顛覆了你對二分查找的認知。哈哈。不是說一定要有序才能用二分查找,只要你確定了某一部分一定有你要找的,你就可以二分下去找。

PS:如果覺得博主寫的還不錯的可以點點贊,關注走一波,謝謝大家的支持~~~

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