如何快速定位出一個IP地址的歸屬地?——二分查詢變體
阿新 • • 發佈:2020-08-03
- 查詢第一個值等於給定值的元素
- 查詢最後一個值等於給定值的元素
- 查詢第一個大於等於給定值的元素
- 查詢最後一個小於等於給定值的元素
- 查詢迴圈有序陣列中等於給定值的元素
#include <iostream> #include <vector> #include <stack> #include <cstring> #include <string> #include <queue> #include <algorithm> #include "TreeNode.h" #include "ListNode.h" using namespace std; // 二分查詢具有O(logn)的時間複雜度,很強,但是隻能用於陣列的資料結構,像連結串列就不適合 // 二分查詢非遞迴法 int binarySearch(int num[], int length, int key){ if(length < 1) return -1; int low = 0; int high = length - 1; int middle = 0; while(low <= high){ // 以後儘量使用位運算,不直接用(low + high) / 2是為了防止加法溢位 middle = low + ((high - low) >> 1); if(num[middle] == key) return middle; if(num[middle] > key) high = middle - 1; else if(num[middle] < key) low = middle + 1; } // 沒找到則返回-1 return -1; } // 二分查詢遞迴方法 int binarySearchPlus(int num[], int low, int high, int key){ if(low > high) return -1; int middle = low + ((high - low) >> 1); if(num[middle] == key) return middle; if(num[middle] > key) return binarySearchPlus(num, low, middle - 1, key); else return binarySearchPlus(num, middle + 1, high, key); } // 查詢第一個值等於給定值的元素 int binarySearchFirst(int num[], int length, int key){ if(length < 1) return -1; int low = 0; int high = length - 1; int middle = 0; int min = 99999; while(low <= high){ // 以後儘量使用位運算,不直接用(low + high) / 2是為了防止加法溢位 middle = low + ((high - low) >> 1); if(num[middle] == key){ // 只可能前面還有 if(middle < min) min = middle; high = middle - 1; } else if(num[middle] > key) high = middle - 1; else if(num[middle] < key) low = middle + 1; } if(min != 99999) return min; // 沒找到則返回-1 return -1; } // 查詢最後一個值等於給定值的元素(妙啊) int binarySearchLast(int num[], int length, int key){ if(length < 1) return -1; int low = 0; int high = length - 1; int middle = 0; int max = -2; while(low <= high){ // 以後儘量使用位運算,不直接用(low + high) / 2是為了防止加法溢位 middle = low + ((high - low) >> 1); if(num[middle] == key){ // 只可能前面還有 if(middle > max) max = middle; low = middle + 1; } else if(num[middle] > key) high = middle - 1; else if(num[middle] < key) low = middle + 1; } if(max != -2) return max; // 沒找到則返回-1 return -1; } // 查詢第一個大於等於給定值的元素(和大於不一樣) int binarySearchFirstHigh(int num[], int length, int key){ if(length < 1) return -1; int low = 0; int high = length - 1; int middle = 0; while(low <= high){ // 如果走到了最後,第一個大於給定值的元素肯定是下一個元素 if(low == high){ if(num[low] != key){ if(low + 1 < length) return low + 1; else return -1; } } // 以後儘量使用位運算,不直接用(low + high) / 2是為了防止加法溢位 middle = low + ((high - low) >> 1); if(num[middle] == key) return middle; if(num[middle] > key) high = middle - 1; else if(num[middle] < key) low = middle + 1; } // 沒找到則返回-1 return -1; } // 查詢第一個大於等於給定值的元素(和大於不一樣)另一種解法,妙啊 int binarySearchFirstHighPlus(int num[], int length, int key){ if(length < 1) return -1; int low = 0; int high = length - 1; int middle = 0; while(low <= high){ middle = low + ((high - low) >> 1); if(num[middle] >= key){ // 妙啊 if(middle == 0 || num[middle - 1] < key) return middle; else // 往左走 high = middle - 1; } else low = middle + 1; } return -1; } // 查詢第一個小於等於給定值的元素(和小於不一樣),妙啊 int binarySearchFirstLowPlus(int num[], int length, int key){ if(length < 1) return -1; int low = 0; int high = length - 1; int middle = 0; while(low <= high){ middle = low + ((high - low) >> 1); if(num[middle] <= key){ if(middle == length - 1 || num[middle + 1] > key) return middle; else // 往右走 low = middle + 1; } else high = middle - 1; } return -1; } // 在迴圈有序陣列中利用二分查詢元素 // 如果加大點兒難度,比如在迴圈有序陣列中查詢第一個等於某值的元素,比如在{3,4,5,6,1,2,3,4,5}中查詢4 int bsearchInCycleSortArray(int num[], int length, int key){ if(length < 1) return -1; int low = 0; int high = length - 1; int middle = 0; while(low <= high){ middle = low + ((high - low) >> 1); if(num[middle] == key) return middle; // 如果中間元素小於尾元素,說明右端是有序的,左端是迴圈的 if(num[middle] < num[high]){ // 如果目標元素在有序陣列範圍中,則後面的都是二分查詢 if(num[middle] < key && key <= num[high]) low = middle + 1; // 如果不在,則在另一半繼續查詢 else high = middle - 1; } // 如果中間元素大於尾元素,說明左端是有序的,右端是迴圈的 else{ // 如果目標元素在有序陣列範圍中,則後面的都是二分查詢 if(num[low] <= key && key < num[middle]) high = middle - 1; // 如果不在,則在另一半繼續查詢 else low = middle + 1; } } return -1; } int main(int argc, char* argv[]){ int arr[6] = {4,5,6,1,2,3}; cout<<bsearchInCycleSortArray(arr, 6, 2)<<endl; return 0; }