国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【二分查找】一文帶你掌握二分法 (附萬能模板)

這篇具有很好參考價值的文章主要介紹了【二分查找】一文帶你掌握二分法 (附萬能模板)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

一、簡介

哪怕沒有學過編程的同學,也許不知道二分法這個名字,但也一定接觸過它的核心思想。不了解的同學也沒關系,我用一句話就能概括出它的精髓:將一個區(qū)間一分為二,每次都舍棄其中的一部分。

二分法能夠極大地降低我們在解決問題時的時間復雜度。假如你要在一個單調(diào)遞增的數(shù)組a[n]中尋找一個數(shù)target,遍歷的話時間復雜度是O(n)。但如果采用二分法,時間復雜度則是O(log n)。這種效率的提高無疑是巨大的!

二、易錯點

1、while循環(huán)中是寫 left < right 還是寫 left <= right ?

2、如下圖所示,if(nums[mid]>target),右邊界更新區(qū)間時是寫成 right = mid 還是 right = mid-1?

二分查找偽代碼,算法,算法,數(shù)據(jù)結(jié)構(gòu),c++,二分法,二分查找

這兩點是很容易弄混的。要弄清楚上面這兩個問題的答案,首先要確定你想寫的循環(huán)的區(qū)間到底是左閉右開還是左閉右閉?(題目沒明確要求的話就看你個人選擇,都是可以的)


左閉右閉的區(qū)間是這樣寫的:[left, right]

它包含了 left 和 right 這兩個數(shù)


左閉右閉的區(qū)間是這樣寫的:[left, right)

它包含了 left,但不包含 right 。


假設我選擇了左閉右閉,此時需要在數(shù)組nums中尋找一個數(shù)target,找到的話返回下標,沒找到的話返回 -1,偽代碼如下:

left=0;
right=nums.size()-1;
while(l <= r){ // 注意這里不是 l < r
	int mid = l + (r - l)/2;
	if(nums[mid] > target) right = mid-1;
	else if(nums[mid] < target) left = mid+1;
	else{
		return mid;
	}	
}

首先,為什么選擇左閉右閉的區(qū)間,第3行就要寫成<=呢?因為寫入while循環(huán)的判斷條件應該與你選擇的區(qū)間相吻合,而左閉右閉的區(qū)間包含了left和right,也就是說可能會出現(xiàn) left== right的情況。如果寫成<,那么就漏掉了left==right 這種情況,所以應該寫成<=。

其次,第5行右邊界為什么更新為 mid-1 而不是更新為 mid?因為我們已經(jīng)確定了nums[mid] > target,所以mid一定不是我們要找的值,因此在下一輪搜索中,不應再包含mid這個數(shù)。而我們選擇的是左閉右閉區(qū)間,它包含了左右邊界,每次搜索時都會包含左右邊界。所以為了使已經(jīng)被排除的mid不被再次搜索,右邊界應該更新為mid-1。


假設我選擇了左閉右開,此時需要在數(shù)組nums中尋找一個數(shù)target,找到的話返回下標,沒找到的話返回 -1,偽代碼如下:

left=0;
right=nums.size();
while(l < r){ // 注意這里不是 l <=r
	int mid = l + (r - l)/2;
	if(nums[mid] > target) right = mid;
	else if(nums[mid] < target) left = mid+1;
	else{
		return mid;
	}	
}
return -1;

左閉右開代表包含左邊界,不包含右邊界。右邊界一定比左邊界大,不存在 right == left 的情況。所以第3行只能寫成<。

而第5行之所以寫成right=mid,是因為下一次搜索中本就不會包含right,我們也確定了right不是要找的值,所以直接寫成right=mid就可以了。

此時,注意第2行,因為左閉右開不包含右邊界,所以右邊界要設置為nums.size(),這樣才能把nums.size()-1包含在搜索區(qū)間里。

三、例子

如果你已經(jīng)理解了上面的內(nèi)容,可以嘗試做下面這道題:

二分查找偽代碼,算法,算法,數(shù)據(jù)結(jié)構(gòu),c++,二分法,二分查找

左閉右閉:

class Solution {
public:
    int search(vector<int>& nums, int target) {
         int l = 0, r =  nums.size() - 1; 
        while(l <= r){ 
            int m = l + (r - l)/2;
            if(nums[m] > target)r = --m;
            else if(nums[m] < target) l = ++m;
            else{
                return m;
            }
        }
    return -1; 
    }
};

左閉右開:

class Solution {
public:
    int search(vector<int>& nums, int target) {
         int l = 0, r =  nums.size(); 
        while(l < r){ 
            int m = l + (r - l)/2;
            if(nums[m] > target)r = m;
            else if(nums[m] < target) l = ++m;
            else{
                return m;
            }
        }
    return -1; 
    }
};

四、萬能模板

盡管理解了上面的內(nèi)容,但很多時候解題還是會遇到困難。

比如說給你一個按照非遞減順序排列的整數(shù)數(shù)組 nums,和一個目標值 target。請你找出給定目標值在數(shù)組中的開始位置和結(jié)束位置。

你會發(fā)現(xiàn)上面的兩個代碼很難應用到這種題,所以我找到了一個萬能模板,跟大家分享一下:

class Solution {
    /**
     * 如果返回值等于 nums.size(),代表 nums 中不存在 滿足 nums[i] >= target 的 i,也就是所有元素都小于 target。
     * 否則返回滿足 nums[i] >= target 的最小 i(最左 i)。也就是說,如果有多個連續(xù)的 target,會返回最靠左的那個的下標。
     * nums為單調(diào)不減數(shù)組
     * target為邊界值  
     **/
    public: int binarySearch(vector<int>& nums, int target) {
        int l = 0, r = nums.size()- 1; // 二分查找的左右初始邊界
        while(l <= r){ // 注意這里不是 l < r
            int m = l + (r - l)/2;
            if(nums[m] >= target)r = --m;
            else l = ++m;
        }
        return l; // 此時,l 代表arr[i] >= x 的最小 i。
    }
};

如何運用這個模板去解決不同的問題呢?請往下看

1、查找某個數(shù) x 首次出現(xiàn)的位置,如果不存在,返回-1。

如果 binarySearch(arr, x) == nums.size(),代表所有元素都小于x,也就無法查找到 x 首次出現(xiàn)的位置;如果有多個元素等于 x,則 binarySearch(arr, x) 代表 x 首次出現(xiàn)的位置的下標;如果binarySearch(arr, x) != x,則不存在某個數(shù)等于 x,binarySearch(arr, x) 代表最靠左的大于 x 的數(shù)。

2、查找某個數(shù) x 最后出現(xiàn)的位置,如果不存在,返回-1。

將該問題轉(zhuǎn)換為用 int ret = binarySearch(arr, x+1) - 1 來解決。 如果ret < 0,返回 -1;否則,如果nums[ret] == x,ret 就是答案;否則,返回 -1。

3、查找某個數(shù) x 首次出現(xiàn)的位置,如果不存在 x,則求出適合插入 x 的位置。

binarySearch(arr, x)就是。

4、查找小于x的最后一個數(shù)。

轉(zhuǎn)換為用binarySearch(arr, x) - 1來解決,注意判斷存在性。

5、查找小于x的第一個數(shù)。

這是個偽問題。

6、查找大于x的第一個的數(shù)。

轉(zhuǎn)換為用binarySearch(arr, x + 1)來解決,注意判斷存在性。

7、查找大于x的最后一個的數(shù)。

這是個偽問題。

舉例:

35. 搜索插入位置

給定一個排序數(shù)組和一個目標值,在數(shù)組中找到目標值,并返回其索引。如果目標值不存在于數(shù)組中,返回它將會被按順序插入的位置。

請必須使用時間復雜度為 O(log n) 的算法。

示例 1:

輸入: nums = [1,3,5,6], target = 5
輸出: 2

示例 2:

輸入: nums = [1,3,5,6], target = 2
輸出: 1

示例 3:

輸入: nums = [1,3,5,6], target = 7
輸出: 4

提示:

  • 1 <= nums.length <= 1 0 4 10^4 104

  • - 1 0 4 10^4 104 <= nums[i] <= 1 0 4 10^4 104

  • nums 為 無重復元素升序 排列數(shù)組

  • - 1 0 4 10^4 104 <= target <= 1 0 4 10^4 104

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int l = 0, r =  nums.size() - 1; // 二分查找的左右初始邊界
        while(l <= r){ // 注意這里不是 l < r
        int m = l + (r - l)/2;
        if(nums[m] >= target)r = --m;
        else l = ++m;
    }
    return l; // 此時,l 代表arr[i] >= tarhget的最小 i。
    }
};

五、參考資料

1、二分查找萬能模板

2、【二分查找】詳細圖解文章來源地址http://www.zghlxwxcb.cn/news/detail-804784.html


??我的個人主頁
??歡迎各位→點贊?? + 收藏?? + 留言???
??總結(jié):希望你看完之后,能對你有所幫助,不足請指正!共同學習交流 ??
??今天你做別人不想做的事,明天你就能做別人做不到的事?


到了這里,關于【二分查找】一文帶你掌握二分法 (附萬能模板)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 二分法簡單題

    2024年01月24日
    瀏覽(27)
  • 【算法】—二分法詳解

    【算法】—二分法詳解

    ①定義: 二分查找算法也稱折半搜索算法,對數(shù)搜索算法,是一種在 有序數(shù)組 中查找某一特定元素的搜索算法。搜索過程從數(shù)組的中間元素開始,如果中間元素正好是要查找的元素,則搜索過程結(jié)束;如果某一特定元素大于或者小于中間元素,則在數(shù)組大于或小于中間元素

    2024年02月09日
    瀏覽(24)
  • 二分法相關使用

    二分法相關使用

    在線OJ:704. 二分查找 有序數(shù)組下的二分思路如下: 由于這里是有序數(shù)組, 我們可以可以先得到中點位置, 中點可以把數(shù)組分為左右兩邊; 如果中點位置的值等于目標值, 直接返回中點位置; 如果中點位置的值小于目標值, 則去數(shù)組中點左側(cè)按同樣的方式查找; 如果中點位置的值大

    2024年02月07日
    瀏覽(17)
  • 初探二分法

    初探二分法

    智能化校園:深入探討云端管理系統(tǒng)設計與實現(xiàn)(一) 智能化校園:深入探討云端管理系統(tǒng)設計與實現(xiàn)(二) 題目:給定一個 n 個元素有序的(升序)整型數(shù)組 nums 和一個目標值 target ,寫一個函數(shù)搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。 提示: 你可以

    2024年01月25日
    瀏覽(22)
  • 二分法MATLAB代碼

    二分法MATLAB代碼

    本質(zhì)是通過不斷進行區(qū)間壓縮來獲取函數(shù)零點。 二分法的終止條件:區(qū)間長度小于等于精度要求 。 流程: 如下圖所示:

    2024年02月05日
    瀏覽(23)
  • 牛頓法、割線法、二分法

    牛頓法、割線法、二分法

    牛頓法求解非線性方程組 割線法求解非線性方程組 二分法求解根號3 ?另外,今天上機課寫程序時,發(fā)現(xiàn)不同的起始點可以收斂到不同的零點。也許這是一個新的值得研究的地方。 看來,計算數(shù)學也是這樣,光聽理論無法實現(xiàn)大的突破,也沒法產(chǎn)生好的想法,必須在實踐應用

    2024年02月05日
    瀏覽(25)
  • 非線性方程二分法

    優(yōu)點:算法直觀、簡單、總能保證收斂;局限:收斂速度慢、一般不單獨用它求根,僅為了獲取根的粗略近似 設 f ( x ) f(x) f ( x ) 在 [ a , b ] [a,b] [ a , b ] 上連續(xù)、嚴格單調(diào)、滿足條件 f ( a ) f ( b ) 0 f(a)f(b)0 f ( a ) f ( b ) 0 則在區(qū)間 [ a , b ] [a,b] [ a , b ] 內(nèi)必有一根 x ? x^* x ? 。通

    2024年02月04日
    瀏覽(27)
  • 【劍指Offer】二分法例題

    【劍指Offer】二分法例題

    鏈表是數(shù)據(jù)結(jié)構(gòu)中重要的一個章節(jié),他的重要性也不言而喻,在未來不管是筆試還是面試都會遇到這類的題目,所以接下來我就會把一些鏈表的??嫉念}目全部整理出來供大家學習指正。 題目鏈接 描述: 給定一個長度為n的數(shù)組nums,請你找到峰值并返回其索引。數(shù)組可能包

    2023年04月13日
    瀏覽(20)
  • 1241:二分法求函數(shù)的零點

    【題目描述】 有函數(shù):f(x)=x5?15x4+85x3?225x2+274x?121 已知f(1.5)0,f(2.4)0 且方程f(x)=0在區(qū)間[1.5,2.41.5,2.4] 有且只有一個根,請用二分法求出該根。 【輸入】 (無) 【輸出】 該方程在區(qū)間[1.5,2.41.5,2.4]中的根。要求四舍五入到小數(shù)點后66位。 【輸入樣例】 【輸出樣例】 【AC代碼】

    2024年01月25日
    瀏覽(21)
  • Leetcode刷題筆記——二分法

    Leetcode刷題筆記——二分法

    二分法是搜索算法中極其典型的方法,其要求輸入序列有序并可隨機訪問。算法思想為 輸入:有序數(shù)組nums,目的數(shù)值target 要求輸出:如果target存在在數(shù)組中,則輸出其index,否則輸出-1 將原數(shù)組通過[left,right]兩個索引劃分范圍,初值left=0,right=數(shù)組的最后一個元素 當left = r

    2024年02月10日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包