1. 程式人生 > >演算法-二分查詢2

演算法-二分查詢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 區間。

總結

本文創作靈感來源於 極客時間 王爭老師的《資料結構與演算法之美》課程,通過課後反思以及借鑑各位學友的發言總結,現整理出自己的知識架構,以便日後溫故知新,查漏補缺。

初入演算法學習,必是步履蹣跚,一路磕磕絆絆跌跌撞撞。看不懂別慌,也別忙著總結,先讀五遍文章先,無他,唯手熟爾~
與諸君共勉

關注本人公眾號,第一時間獲取最新文章釋出,每日更新一篇技術文章。

在這裡插入圖片描述