二分查詢-不套用模板
二分查詢-不套用模板
這裡參考自大佬 https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/
體會:
- 使用減治思想,在迴圈體內排除元素。同樣如果寫成<=的形式表示從迴圈體內找到元素。
while(first<last)
- 最後退出的時候一定是left和right相等的時候,所以無所謂返回誰。
return left;
- 寫成下面這樣而不寫成(left+right)/2主要是避免兩者相加會溢位。
- mid的求法屬於向下取整,即left+1=right的時候mid=left+0,如果下面更新的時候存在left=mid這樣的賦值會形成死迴圈(應該通過調整left和right的if-else的大於小於條件更新避免出現left=mid這種形式更新)。
mid=left+(right-left)/2;
left=mid;
- 如何縮減?如下列註釋
//這裡mid下標對應的元素值小於target,故mid應該排除出去。
if(nums[mid]<target)//[mid+1,right]
left=mid+1;
else//與上面對稱,是[left,mid]
right=mid;
例項程式碼
形式可能千變萬化,根據需要進行調整。
- 陣列可能升序可能降序,但是可以通過函式預處理
- 寫【left,right】兩邊都閉區間的形式,保障都能取到
- while寫成小於的形式,保障退出的時候left=right
- left和right的值更新是互補的形式,避免寫left=mid造成死迴圈
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
//求非降序範圍[first, last]內第一個不小於value的值的位置
int len=size(nums);
int left=0;
int right=len-1;
int mid;
while(left<right)//搜尋區間[first, last)不為空
{
mid=left+(right-left)/2;//防溢位
if(nums[mid]<target)
left=mid+1;
else
right=mid;
}
return left;//last也行,因為[first, last)為空的時候它們重合
}
};
題型一:在陣列中查詢符合條件的元素的下標
非模板做法:
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0,right=nums.size()-1;
int mid;
while(left<right)
{
mid=left+(right-left)/2;
if(nums[mid]<target)
{
left=mid+1;
}
else
{
right=mid;
}
}
if(nums[left]==target)
return left;
else
return -1;
}
};
模板做法:
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0,right=nums.size()-1;
int mid;
while(left<=right)
{
mid=left+(right-left)/2;
if(nums[mid]>target)
{
right=mid-1;
}
else if(nums[mid]<target)
{
left=mid+1;
}
else
return mid;
}
return -1;
}
};
非模板做法:
在這裡插入程式碼片
模板做法:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> temp;
int left=0,right=nums.size()-1;
int mid;
int start=0,end=0;
//找左邊界
while(left<=right)
{
mid=left+(right-left)/2;
if(nums[mid]>target)
right=mid-1;
else if(nums[mid]<target)
left=mid+1;
else if(nums[mid]==target)
right=mid-1;
}
if(left>=nums.size() || nums[left]!=target)
left=-1;
start=left;
temp.push_back(left);
//找右邊界
left=0;
right=nums.size()-1;
while(left<=right)
{
mid=left+(right-left)/2;
if(nums[mid]>target)
right=mid-1;
else if(nums[mid]<target)
left=mid+1;
else if(nums[mid]==target)
left=mid+1;
}
if(right<0 || nums[right]!=target)
right=-1;
end=right;
temp.push_back(right);
return temp;
}
};
總結:
- 基本思路:二分法先獲取山頂元素的下標,分成升序和降序兩部分,利用二分法尋找目標元素的下標
- 首先是山頂元素的獲取,沒有直接利用三者關係,而是利用兩者的關係從兩邊不斷地向中間靠攏縮減,減少了訪問次數。得到山頂元素可以先判斷一下是不是目標元素,減少運算量
/**
* // This is the MountainArray's API interface.
* // You should not implement it, or speculate about its implementation
* class MountainArray {
* public:
* int get(int index);
* int length();
* };
*/
class Solution {
public:
int findMountainTop(MountainArray &mountainArr,int target,int left,int right)
{
int mid;
//直接使用兩個不等式約束,條件過於緊
while(left<right)
{
mid=left+(right-left)/2;
if(mountainArr.get(mid)<mountainArr.get(mid+1))
{
left=mid+1;//左側削減
}
else
{
right=mid;//右側削減
}
}
return left;//lef==right
}
int findSortedArray(MountainArray &mountainArr,int target,int left,int right)
{
int mid;
while(left<right)//去排除一定不存在元素的空間
{
mid=left+(right-left)/2;
if(mountainArr.get(mid)<target)
{
//[mid+1,right]
left=mid+1;
}
else
{
//[left,mid]
right=mid;
}
}
return left;
}
int findReverseArray(MountainArray &mountainArr,int target,int left,int right)
{
//注意:可以在大於小於上做文章避免出現left=mid這種向下取整導致的死迴圈問題
int mid;
while(left<right)//去排除一定不存在元素的空間
{
//向下取整。mid=left+0,所以應當避免下面出現left=mid的賦值導致死迴圈
mid=left+(right-left)/2;
if(mountainArr.get(mid)>target)
{
//[mid+1,right]
left=mid+1;
}
else
{
//[left,mid]
right=mid;
}
}
return left;
}
int findInMountainArray(int target, MountainArray &mountainArr) {
int index=-1;
//獲取陣列長度
int len=mountainArr.length();
//尋找最大值下標
int peakIndex=findMountainTop(mountainArr,target,0,len-1);
//判斷最大值下標位置是不是目標值
if(mountainArr.get(peakIndex)==target)
return peakIndex;
//升序陣列部分尋找target
index=findSortedArray(mountainArr,target,0,peakIndex-1);
if(mountainArr.get(index)==target)
return index;
//降序陣列部分尋找target
index=findReverseArray(mountainArr,target,peakIndex+1,len-1);
if(mountainArr.get(index)==target)
return index;
else
return -1;
}
};
相關文章
- python二分查詢模板Python
- leetcode解題模板 —— 二分查詢LeetCode
- 二分查詢基礎專題——二分模板
- 查詢——二分查詢
- 二分查詢 - 手寫模板與自帶函式函式
- 二分查詢(一)——純粹的二分查詢
- 二分查詢
- 查詢演算法__二分查詢演算法
- 十分好用的二分查詢模板 手撕二分還怕嗎?
- 二分查詢法
- PHP二分查詢PHP
- leetcode——二分查詢LeetCode
- leetcode -- 二分查詢LeetCode
- 查詢演算法之二分查詢演算法
- 二分查詢 | 二分查詢的一種推薦寫法
- 704.二分查詢
- labuladong_二分查詢
- 詳解二分查詢
- 二分查詢(c++)C++
- 每日leetcode——二分查詢LeetCode
- Leetcode 704 二分查詢LeetCode
- 二分查詢【折半查詢】演算法 PHP 版演算法PHP
- 【演算法】二分查詢演算法
- 演算法->二分查詢演算法
- 力扣之二分查詢力扣
- 二分查詢的定義
- 二分搜尋(折半查詢)
- PHP 實現二分查詢PHP
- 圖解--二分查詢樹圖解
- 二分查詢成長錄
- 牛客網 查詢(二分查詢、北郵機試)
- 陣列的查詢(搜尋):線性查詢和二分法查詢陣列
- 二分查詢 理論 例題
- LeetCode演算法—二分查詢LeetCode演算法
- 基礎二分查詢總結
- 二分查詢的簡單理解
- 二分查詢法(Binary_Search)
- 聊一聊二分查詢法