二分查詢—包括查詢第一個目標元素和最後一個目標元素
學了沒過多久又忘了,在這裡寫一下筆記。此處主要學習參考了labuladong寫的二分查詢筆記,我加上了我自己的理解。
二分查詢需要明確:
- 查詢條件:找到中間的元素,還是找到多個目標元素第一個(最左邊)的元素,還是多個目標元素的最後一個
- 查詢區間:左閉右閉
while(left<=right)
,左閉右開while(left<right)
。
需要判斷什麼時候區間中沒有元素,來作為判別條件。在while(left<=right)時,[left+1,left]區間中沒有元素,退出迴圈。
while(left<right)時,[left,left)中沒有元素,退出迴圈。
但其實左閉右開可以轉換成左閉右閉。 - 什麼時候返回查詢到的目標元素的下標:
- 找到中間元素:找到立即返回
- 找邊界目標元素:找到目標,不斷縮小區間返回。
- 找左邊界:
if(nums[mid] == target) right=mid;
- 找右邊界:
if(nums[mid] == target) left=mid+1;
- 找左邊界:
- 邊界元素需要在迴圈外面打補丁:
- 找左邊界:
if(left==len) return 0;
目標元素比陣列所有元素都大,返回-1 - 找右邊界:
if(left==0) return -1;
目標元素比陣列所有元素都小,返回-1
- 找左邊界:
- 邊界目標元素的返回:
- 左邊界:當區間縮小到只有兩個元素,且這兩個元素相同的時候,while條件會漏掉,返回打補丁
return nums[left] == target ? left : -1;
- 右邊界:因為找到目標元素,左邊界向右縮排,left=mid+1。當while結束時,nums[left]一定不等於target,即相當於left來到了目標元素的後面一個位置,但是nums[left-1]有可能目標元素的右邊界,返回打補丁
return nums[left-1] == target ? (left-1) : -1;
- 左邊界:當區間縮小到只有兩個元素,且這兩個元素相同的時候,while條件會漏掉,返回打補丁
一般查詢元素
int search(vector<int>& nums, int target) {
int len=nums.size();
if(len == 0) return -1;
int left=0,right=nums[len-1];//閉區間
while(left<=right){//閉區間中不含元素的判定[left+1,left]
int mid=left+(right-left)/2;
if(nums[mid] == target){
return mid;//找到元素立即返回,找左右邊界元素不是找到立即返回,而是繼續縮小區間
}
else if(nums[mid] > target){
right=mid-1;//閉區間,從mid分割開
}
else if(nums[mid] < target){
left=mid+1;
}
}
return -1;//沒有找到元素
}
下面的兩個程式碼好像我寫的有問題,部分可以成功返回下標,部分返回-1
找第一個目標元素
int left_bound(vector<int>& nums, int target){
int len=nums.size();
if (len == 0) return -1;
int left=0,right=len;
while(left < right){//因為右邊界取不到索引
int mid=left+(right-left)/2;
if(nums[mid]==target){
right=mid;//縮小邊界,不斷向左邊界靠近
}
else if(nums[mid]>target){
right=mid;
}
else if(nums[mid]<target){
left=mid+1;
}
//目標元素比陣列中的所有元素都大
if(left==len) return -1;
//反之區間只有兩個元素時,且剛好是兩個相同的元素
return nums[left]==target ? left : -1;
}
}
int main(){
vector<int> nums;
nums.push_back(0);nums.push_back(1);nums.push_back(1);nums.push_back(2);nums.push_back(3);
int ans=left_bound(nums,4);
cout<<ans<<endl;
return 0;
}
找最後一個目標元素
int right_bound(vector<int>& nums,int target){
int len=nums.size();
if l(en == 0) return -1;
int left=0,right=len;
while(left < right){//因為右邊界取不到索引
int mid=left+(right-left)/2;
if(nums[mid]==target){
//不斷向右邊界靠近
left=mid+1;
}
else if(nums[mid]>target){
right=mid;
}
else if(nums[mid]<target){
left=mid+1;
}
//沒找到右邊界
if(left==0) return -1;
//因為找到目標,左邊界向有縮排,left=mid+1。當while結束時,nums[left]一定不等於target,而nums[left-1]有可能是
return nums[left -1] == target ? (left-1) : -1;
}
int main(){
vector<int> nums;
nums.push_back(0);nums.push_back(1);nums.push_back(1);nums.push_back(2);nums.push_back(3);
int ans=right_bound(nums,1);
cout<<ans<<endl;
}
相關文章
- 在排序陣列中查詢元素的第一個和最後一個位置排序陣列
- 34. 在排序陣列中查詢元素的第一個和最後一個位置(中)排序陣列
- c++map 查詢元素和list查詢元素速度對比C++
- jQuery查詢第n個li元素jQuery
- 【Java】陣列二分查詢元素Java陣列
- Java 實現二分查詢(在 1-100 裡找到目標值)Java
- jQuery之元素查詢jQuery
- 二分只能用來查詢元素嗎?
- 遞迴查詢子元素遞迴
- 34、在排序陣列中查詢元素的第一個和最後一個位置 | 演算法(leetode,附思維導圖 + 全部解法)300題排序陣列演算法
- js 從目標陣列中過濾掉 一個陣列元素,JS陣列
- 遊標查詢
- 查詢——二分查詢
- 二分搜尋之搜尋陣列中目標元素的首尾下標陣列
- 查詢最大元素 hd 2025
- 陣列的主元素查詢陣列
- jquery如何獲取第一個或最後一個子元素?jQuery
- 二分查詢(一)——純粹的二分查詢
- 如何查詢上標
- MYSQL學習筆記25: 多表查詢(子查詢)[標量子查詢,列子查詢]MySql筆記
- 查詢Set中重複的元素
- c++中的查詢list元素C++
- Java中查詢列表的峰值元素Java
- C語言:10個元素整型陣列,最小值和第一個元素交換,最大值與最後一個元素交換C語言陣列
- 391、Java框架46 -【Hibernate - 查詢HQL、查詢Criteria、查詢標準SQL】 2020.10.19Java框架SQL
- 使用MASA Blazor開發一個標準的查詢表格頁Blazor
- 查詢演算法__二分查詢演算法
- 【LeetCode-陣列】查詢大多數元素LeetCode陣列
- Elasticsearch 按照標籤匹配個數優先排序查詢Elasticsearch排序
- 影響Oracle標量子查詢效能的三個因素Oracle
- 二分查詢 | 二分查詢的一種推薦寫法
- mysql 標量子查詢和現金盤程式製作非法子查詢MySql
- <二分查詢+雙指標+字首和>解決子陣列和排序後的區間和指標陣列排序
- 陣列的查詢(搜尋):線性查詢和二分法查詢陣列
- RedMonk分析師包括Flux查詢語言和Telegraf指標代理等UX指標
- 查詢演算法之二分查詢演算法
- 二分查詢
- jQuery查詢帶有class樣式的元素jQuery