日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法二——二分查找

發布時間:2023/12/10 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法二——二分查找 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章出處:極客時間《數據結構和算法之美》-作者:王爭。該系列文章是本人的學習筆記。

思考題目

1 用最省內存的方式查找數據。
2 快速定位ip所在省市

二分查找的速度

二分每次都通過跟區間中的中間元素對比,將待查找的區間縮小為一半,直到區間為0或者找到元素。需要重點關注退出條件、mid取值、low和high的更新。

二分的時間復雜度O(logn)。logn少的驚人之處和指數的大的驚人之處類似。2的32次方是4億多。在4億多有序數組中查找數據,只需要32次。很少吧。

簡單代碼實現

簡單是因為數組中沒有重復數據。

public static int easySearch(int[] a,int value){if(a==null) return -1;int n = a.length;int low = 0;int high = n-1;return easySearch(a, value, low, high);}private static int easySearch(int[] a,int value,int low,int high){if(low>high) return -1;int mid = low + ((high-low)>>1);if(value==a[mid]) return mid;if(value<a[mid]) return easySearch(a,value,low,mid-1);return easySearch(a,value,mid+1,high);}

二分的應用場景

1 二分依賴的是順序表,也就是數組。鏈表復雜度變高。因為鏈表隨機查找的時間復雜度是O(n)。
如果使用鏈表,第一次查找a[mid],需要n2\dfrac{n}{2}2n?次查找,第二次查找a[mid],需要n4\dfrac{n}{4}4n?次查找,依次類推所需要的查找有sum=n2+n4+n8+....+1=n?1sum=\dfrac{n}{2}+\dfrac{n}{4}+\dfrac{n}{8}+....+1=n-1sum=2n?+4n?+8n?+....+1=n?1。時間復雜度O(n)。

2 二分針對的是有序數據。在插入、刪除比較少的場景中,可以將排序的時間成本均攤到查詢上面。插入、刪除多,則復雜度升高。

3 數據量小不能體現二分的優勢。例如10個數據。無論順序查找還是二分,時間差不多。

4 數據量不能太大。因為二分依賴數組存儲數據,數組要求連續的內存。

思考題

在100M內存中,查找1000萬整數的某個數。如果用long表示整數,一個整數8個字節,1000萬整數,80M內存。可以先使用空間復雜度低的排序算法排序,之后二分查找。

求一個數的平方根,精確到小數點后6位。

二分的變體

查找第一個等于value的元素的位置

public static int findFirstEqualElement(int[] a ,int value){if(a==null) return -1;int n = a.length;int low = 0;int high = n-1;while(low<=high){int mid = low + ((high-low)>>1);if(value<a[mid]){high = mid - 1;}else if(value>a[mid]){low = mid +1;}else{if(mid==0 || a[mid-1]!=value)return mid;elsehigh = mid-1;}}return -1;}

最后一個等于value的元素的位置

public static int findLastEqualElement(int[] a ,int value){if(a==null) return -1;int n = a.length;int low = 0;int high = n-1;while(low<=high){int mid = low + ((high-low)>>1);if(value<a[mid]){high = mid - 1;}else if(value>a[mid]){low = mid +1;}else{if(mid==n-1 || a[mid+1]!=value)return mid;elsehigh = mid-1;}}return -1;}

查找第一個大于等于value的元素的位置

public static int findFirstMoreOrEqualElement(int[] a ,int value){if(a==null) return -1;int n = a.length;int low = 0;int high = n-1;while(low<=high){int mid = low + ((high-low)>>1);if(value<=a[mid]){if(mid==0 || a[mid-1]<value) return mid;high = mid - 1;}else if(value>a[mid]){low = mid +1;}}return -1;}

查找最后一個小于等于value的元素的位置

public static int findLastLessOrEqualElement(int[] a ,int value){if(a==null) return -1;int n = a.length;int low = 0;int high = n-1;while(low<=high){int mid = low + ((high-low)>>1);if(value<a[mid]){high = mid - 1;}else if(value>=a[mid]){if(mid==n-1 || a[mid+1]>value)return mid;low = mid +1;}}return -1;}

思考題

快速定位ip所在省市。可以用一個32位的int表示一個ip地址。查找每一個ip段內,最后一個起始ip小于等于目標ip的ip段,然后查找目標ip是不是在這個范圍內。

循環有序數據的二分查找怎么解決,數組是升序。
 需要先找到第一個a[i]&lt;a[i+1]a[i]&lt;a[i+1]a[i]<a[i+1],例如數組nums={4,5,6,7,0,1,2}。i應該等于4。然后我們可以選擇將數組復制一下成為{0,1,2,4,5,6,7},但是這樣時間復雜度就會是O(n)。我們也可以這樣看nums[4]=0,nums[5]=1,nums[6]=2,nums[7]=4,nums[8]=5,nums[9]=6,nums[10]=6。相當于將nums看做是一個循環數組。

public int search(int[] nums, int target) {int n = nums.length;int low = 0;int high = n-1;while(low<high){int mid = (low+high)/2;if(nums[mid]>nums[high]){low = mid +1;}else{high = mid;}}int rotatedIndex = low;low = 0;high = n-1;while(low<=high){int mid = (low+high)/2;int realMid = (mid+rotatedIndex)%n;if(nums[realMid]<target){low = mid+1;}else if(nums[realMid]>target){high = mid-1;}else{return realMid;}}return -1;}

總結

以上是生活随笔為你收集整理的算法二——二分查找的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。