再也不怕女朋友問我二分查找了!【手繪漫畫】圖解二分查找(修訂版)(LeetCode 704題)

在這裏插入圖片描述

圖解算法與數據結構

1、前言

上次講到的更的二分查找模板在很多地方讓我使用起來不是特別的舒服,感謝B站上的y大佬,讓我找到了一個新的模板!!!
在這裏插入圖片描述
下面一起來看看吧!!!
在這裏插入圖片描述
本次的模板應對重複元素也可以~
在這裏插入圖片描述
在這裏插入圖片描述

2、代碼

模板一:

// C
int lower_bound(int* nums, int numsSize, int target){
	int left = 0;
	int right = numsSize-1;
	while(left < right){	// 搜索區間[first, last)不爲空
		// 防溢出
		int mid = left + right >> 1;
		if(nums[mid] >= target) right = mid;
		else left = mid + 1;
	}
	return left;			// right也行,因爲[left, right)爲空的時候它們重合
}

首先一定要明確,數組是升序的!!!

如果中點大於等於 target,表示目標在左側,數組範圍應該從 [left, right] 變成 [left, mid],否則,就從 [left, right] 變成 [mid+1, right]

爲什麼 right 不加一?

因爲是大於等於,帶着等於,也就是 mid 有可能是我們的解!!!
在這裏插入圖片描述


模板二:

// C
int lower_bound(int* nums, int numsSize, int target){
	int left = 0;
	int right = numsSize-1;
	while(left < right){	// 搜索區間[first, last)不爲空
		// 防溢出
		int mid = left + right + 1 >> 1; // 防止死循環,mid加1
		if(nums[mid] <= target) left = mid;
		else right = mid + 1;
	}
	return left;			// right也行,因爲[left, right)爲空的時候它們重合
}

首先一定要明確,數組是升序的!!!

如果中點小於等於 target,表示目標在右側,數組範圍應該從 [left, right] 變成 [mid, right],否則,就從 [left, right] 變成 [left, mid+1]

爲什麼 left 不加一?

因爲是小於等於,帶着等於,也就是 mid 有可能是我們的解!!!
在這裏插入圖片描述

  • 模板一:區間 [left, right] 劃分成 [left, mid][mid + 1, right] 時,其更新操作是 right = mid 或者 left = mid + 1;,計算 mid 時不需要加 1
  • 模板二:區間 [left, right] 劃分成 [left, mid - 1][mid, right] 時,其更新操作是 r = mid - 1 或者 l = mid;,此時爲了防止死循環,計算 mid 時需要加 1

在這裏插入圖片描述

3、實例(LeetCode 704題)

首先看一下題目,
在這裏插入圖片描述
代碼:

int search(int* nums, int numsSize, int target){
    int left=0;
    int right=numsSize-1;
    while(left<right){
        int mid=left+right >> 1;
        if(nums[mid]>=target){
            right=mid;
        }
        else{
            left=mid+1;
        }
    }
    if(nums[left]==target) return left;
    return -1;
}

在這裏插入圖片描述
作爲最經典的二分查找題,這個題依舊複合我們的模板,沒錯就是 模板一!!!

唯一不同的是,要注意判斷結果,不能只寫個 left ,因爲是存在 -1 的情況的,加個 if(nums[left]==target) return left; 就好了。

這裏自然又更容易的方法,但是 練習模板,萬法接通,每日一遍,養成習慣!!!
在這裏插入圖片描述
附上最經典的二分查找解法:

// C
int search(int* nums, int numsSize, int target){
    int left = 0;
    int right = numsSize - 1;

    while (left <= right) {
    	// 最好這麼寫,不然會內存溢出
    	// 同時還能減少運行時間!!!
        int mid = (left + right) >> 1;
        // 等於的情況最簡單,首先判斷,沒準一下就中了!
        if (nums[mid] == target) {
            return mid;
        }
        else if (nums[mid] < target) {
            // 左邊界更新爲 mid + 1
            left = mid + 1;
        }
        else {
            // 右邊界更新爲 mid - 1
            right = mid - 1;
        }
    }
    return -1;
}

在這裏插入圖片描述
在這裏插入圖片描述

如果有幸幫到你,請幫我點個【贊】,給個【關注】!如果能順帶【評論】給個鼓勵,我將不勝感激。

如果想要更多的資源,歡迎關注 @我是管小亮,文字強迫症MAX~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章