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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

(图文)二分查找,查指定值、小于或等于k的最大值,大于或等于k的最大值

發布時間:2023/12/13 综合教程 30 生活家
生活随笔 收集整理的這篇文章主要介紹了 (图文)二分查找,查指定值、小于或等于k的最大值,大于或等于k的最大值 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們經常會用到二分查找
二分查找應該很多人都會寫了,今天要寫一個用二分查找找到小于k的最大值的時候看了很久不懂他設計的思路,后來想通了,記錄一下。
所以這篇主要是講 用二分查找找到小于k的最大值大于k的最大值

二分查找查找指定值

這個挺簡單的,直接上代碼吧

 //獲取值是k的位置,找不到則返回-1
    public static int getK(int[] a, int k){
        if(a.length == 0){
            return -1;
        }
        int l = 0;
        int r = a.length - 1;
        //注意這里的判斷條件,是必須允許 l = r 的情況存在的
        //因為可能會出現剛好到最后左邊指針到右邊指針只有1個元素,而且這個元素恰恰就是我們想找的k
        while (l <= r){
            int mid = (l + r) / 2;
            //如果mid元素已經是k了,那么直接返回
            if (a[mid] == k){
                return mid;
            //查找左邊的
            }else if(a[mid] > k) {
                r = mid - 1;
            //查找右邊的
            }else {
                l = mid + 1;
            }
        }
        //如果沒有找到指定的值,那么直接返回-1
        return -1;
    }

用二分查找找到小于或者等于k的最大值

思路:如果mid元素是小于或等于k,往右找,如果大于k,往左邊找,直到找到一個值,最接近與k的。
看代碼中標注了 處地方,下面解釋為什么如此設計

    //獲取值<=k的最大值
    public static int uperK(int[] a, int k){
        int l = 0;
        int r = a.length - 1;
        //標注1: 這里是l<r,
        while(l < r){
            //標注2: 這樣的操作是為了取高位
            int mid = (l + r + 1) / 2;
            if(a[mid] <= k) { //標注3:因為a[mid]<=k,所以a[mid]可能=k,所以mid坐標也滿足條件,l = mid而不是mid+1;
                l = mid;
            }else{
                r= mid - 1; //這是a[mid] > k的時候。
            }
        }
        //標注4: 因為此時求得到的是最接近于目標值k的數,
        // 如果最小值都大于k的話,那么就沒有辦法得到了,所以就進行一個判斷
        if(a[l] > k) return -1;
        //標注5: 其實這里無論返回 a[l] 還是a[r]都行,循環的退出時間是l == r 的時候
        return a[l];
    }

標注1解釋:
因為我們的目的是“通過縮小范圍,得到當l = r的時候,l 標記的值”的情況,所以直到 l< r條件被打破的時候的l就是我們要求的值。這跟上一道問題“查找指定值”是不一樣的

標注2解釋:
標注2: 這樣的操作是為了讓 mid 標志 取高位, 才能讓循環順序跳出來,舉個死循環的例子
注意這個例子采取的是mid = (l + r) / 2 取低位的情況,為了展示死循環的形成過程,我們原題的做法是取高位的

數據: int[] num = {1,2,3,4,5,6,7,8,9}, 查找小于或者等于8的最小值。


如上圖,此時左坐標是0, 右是8, 那么
mid = (0 + 8) / 2 = 4,num[mid] = num[4] <= k, ,向右找結果,所以有 l = mid,開始下一個循環。


此時的mid = 6, num[6] = 7;
num[mid] <= k, 向右找 l = 6
下一步:

可以得到 l = 6, r = 8, mid = (6+8) / 2 = 7,a[7] = 8 <= k,那么有l = mid = 7, r = 8,
推到得到mid = 7, 問題來了上一步的時候mid已經是7了,結果會使得mid一直是7,一直循環下去。
所以如果我們求的是二分法求小于或者等于k的最大值的話,我們mid 必須取得中值的上界,

標注3解釋:
因為a[mid]<=k,所以a[mid]可能=k,所以mid坐標也滿足條件,l = mid而不是mid+1;
標注4解釋:
如果最小值都大于k的話,那么就沒有辦法得到了,所以就進行一個判斷
最典型的例子是:
{1,2,3,4,5,6,7,8} ,然后k是0的時候, 這樣得到的結果只能是數組中最接近與k的數,但是如果他還是大于k
你們可以算一下上面這個例子,到最后num[l] 是1, 永遠都大于0, 那么得返回取不到值,所以return -1;
標注5解釋:
其實這里無論返回 a[l] 還是a[r]都行,循環的退出時間是l == r 的時候

二分查找大于或等于k的最小值

直接上代碼了,想必大家都清楚了,看了上面問題2的解釋

public static int downK(List list, int key){
    while (low < high) {
                //這里進行的是取低位, 也是為了使得循環可以正確退出,防止死循環
		int mid = (low + high)/2;
		if (a[mid] < key) {
		    low = mid +1;
		} else { //a[mid] >= key
		    high = mid;   //因為mid也滿足情況
		}
	}
            //這里進行檢查的原因參考上面的標注
	if (a[high] >= key) {
		return high;
	} else {
	    return -1;
	}
}

總結

以上是生活随笔為你收集整理的(图文)二分查找,查指定值、小于或等于k的最大值,大于或等于k的最大值的全部內容,希望文章能夠幫你解決所遇到的問題。

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