演算法-二分查詢2
如何快速定位IP對應的省份
二分查詢的四種變形:查詢第一個值等於給定值得元素,查詢最後一個值等於給定值得元素,查詢第一個大於等於給定值得元素,查詢最後一個小於等於給定值得元素。
同時,今天的這四種情況,給定資料集合同樣是有序的,但是卻有重複元素。
變體一:查詢第一個值等於給定值得元素
先看程式碼:
public static int searchOne(int[] list,int num){
int low = 0;
int high = list.length - 1;
while(low <= high){
int mid = (high + low)/2;
if(list[mid] > num){
high = mid - 1;
}else if(list[mid] < num){
low = mid + 1;
}else{
if(list[mid] == num && list[mid - 1] < num){
return mid;
}else{
high = mid - 1;
}
}
}
return -1;
}
上述程式碼中,對於 list[mid] 大於或者小於給定值的判斷邏輯很好理解,重點解釋下 list[mid] 等於給定值的時候如何做出判斷。
當 list[mid] 等於給定值得時候,因為陣列是按照從小到大順序排列,所以我們要根據 mid 前一位的值做出後續的邏輯判斷。如果 list[mid - 1] 小於給定值,則證明 mid 位置上是第一個給定值的元素,否則就需要令 high = mid - 1,繼續二分查詢。
變體二:查詢最後一個值等於給定值得元素
先看程式碼:
//二分法查詢變體二,查詢最後一個值等於給定值得元素
public static int searchTwo(int[] list,int num){
int low = 0;
int high = list.length - 1;
while (low <= high){
int mid = (high + low)/2;
if(list[mid] > num){
high = mid - 1;
}else if(list[mid] < num){
low = mid + 1;
}else{
if(list[mid] == num && list[mid + 1] > num){
return mid;
}else{
low = mid + 1;
}
}
}
return -1;
}
當 list[mid] 等於給定值得時候,因為陣列是按照從小到大順序排列,所以我們要根據 mid 前一位的值做出後續的邏輯判斷。如果 list[mid + 1] 大於給定值,則證明 mid 位置上是最後一個給定值的元素,否則就需要令 low = mid + 1,繼續二分查詢。
變體三:查詢第一個值大於給定值得元素
先看程式碼:
//二分法查詢變體三,查詢第一個值大於給定值得元素
public static int searchThree(int[] list,int num){
int low = 0;
int high = list.length - 1;
while(low <= high){
int mid = (high + low)/2;
if(list[mid] > num){
high = mid - 1;
}else if(list[mid] < num){
low = mid + 1;
}else{
if(list[mid] == num && list[mid + 1] > num){
return mid + 1;
}else{
low = mid + 1;
}
}
}
return -1;
}
當 list[mid] 等於給定值得時候,因為陣列是按照從小到大順序排列,所以我們要根據 mid 前一位的值做出後續的邏輯判斷。如果 list[mid + 1] 大於給定值,則證明 mid + 1 位置上第一個值大於給定值得元素,否則就需要令 low = mid + 1,繼續二分查詢。
變體四:查詢第一個值小於給定值得元素
先看程式碼:
//二分法查詢變體四,查詢第一個值小於給定值得元素
public static int searchFour(int[] list,int num){
int low = 0;
int high = list.length - 1;
while(low <= high){
int mid = (high + low)/2;
if(list[mid] > num){
high = mid - 1;
}else if(list[mid] < num){
low = mid + 1;
}else{
if(list[mid] == num && list[mid - 1] < num){
return mid - 1;
}else{
high = mid - 1;
}
}
}
return -1;
}
當 list[mid] 等於給定值得時候,因為陣列是按照從小到大順序排列,所以我們要根據 mid 前一位的值做出後續的邏輯判斷。如果 list[mid - 1] 小於給定值,則證明 mid - 1 位置上第一個值大於給定值得元素,否則就需要令 high= mid - 1,繼續二分查詢。
如何快速定位IP對應的省份
因為 IP 地址可以轉化為 32 位整數,所以先對IP地址資料排序。然後用二分查詢找到第一個 IP 起始地址小於給定地址的資料,然後在判斷給定地址是否在該資料 IP 區間。
總結
本文創作靈感來源於 極客時間 王爭老師的《資料結構與演算法之美》課程,通過課後反思以及借鑑各位學友的發言總結,現整理出自己的知識架構,以便日後溫故知新,查漏補缺。
初入演算法學習,必是步履蹣跚,一路磕磕絆絆跌跌撞撞。看不懂別慌,也別忙著總結,先讀五遍文章先,無他,唯手熟爾~
與諸君共勉