二分查詢—包括查詢第一個目標元素和最後一個目標元素
學了沒過多久又忘了,在這裡寫一下筆記。此處主要學習參考了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. 在排序陣列中查詢元素的第一個和最後一個位置(中)排序陣列
- jquery 查詢某個元素的父元素jQuery
- 【Java】陣列二分查詢元素Java陣列
- jQuery查詢第n個li元素jQuery
- jQuery查詢下一個緊鄰兄弟元素jQuery
- 微策略面試題:在旋轉後的陣列中查詢元素(二分查詢)面試題陣列
- 二分只能用來查詢元素嗎?
- Java 實現二分查詢(在 1-100 裡找到目標值)Java
- 標量子查詢(一)
- jQuery之元素查詢jQuery
- js 從目標陣列中過濾掉 一個陣列元素,JS陣列
- 順序查詢和二分查詢
- 遊標查詢
- 標量子查詢
- 查詢——二分查詢
- 二分搜尋之搜尋陣列中目標元素的首尾下標陣列
- 34、在排序陣列中查詢元素的第一個和最後一個位置 | 演算法(leetode,附思維導圖 + 全部解法)300題排序陣列演算法
- jquery如何獲取第一個或最後一個子元素?jQuery
- 二分查詢(一)——純粹的二分查詢
- 查詢某個表最後修改時間
- 利用jQuery查詢子元素和父元素程式碼例項jQuery
- 陣列的主元素查詢陣列
- 1230 元素查詢
- js查詢陣列元素位置JS陣列
- Selenium webdriver Java 查詢元素WebJava
- 標量子查詢(二)
- 不會改變操作物件內容的STL演算法(元素查詢,序列查詢,統計元素個數,比較區間,找最值)物件演算法
- 怎樣查詢一個表的最後更新時間?
- php獲取並刪除陣列的第一個和最後一個元素PHP陣列
- MYSQL學習筆記25: 多表查詢(子查詢)[標量子查詢,列子查詢]MySql筆記
- C語言:10個元素整型陣列,最小值和第一個元素交換,最大值與最後一個元素交換C語言陣列
- Python查詢-二分查詢Python
- 通過資料庫鏈查詢會導致源和目標庫SCN同步資料庫
- SSM整合_年輕人的第一個增刪改查_查詢SSM
- 查詢Set中重複的元素
- 通過clss屬性查詢元素
- Java中查詢列表的峰值元素Java
- c++中的查詢list元素C++