二分查找
二分查找也稱折半查找(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:如果覺得博主寫的還不錯的可以點點贊,關注走一波,謝謝大家的支持~~~