【分模組練習】二分查詢
二分查詢思路簡單,但細節很搞人。個人習慣用左閉右開的區間寫法,以下是模板:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int n = nums.size();
int left = 0;
int right = n; // 我們定義target在左閉右開的區間裡,[left, right)
while (left < right) { // 因為left == right的時候,在[left, right)是無效的空間
int middle = left + ((right - left) >> 1);
if (nums[middle] > target) {
right = middle; // target 在左區間,因為是左閉右開的區間,nums[middle]一定不是我們的目標值,所以right = middle,在[left, middle)中繼續尋找目標值
} else if (nums[middle] < target) {
left = middle + 1; // target 在右區間,在 [middle+1, right)中
} else { // nums[middle] == target
return middle; // 陣列中找到目標值的情況,直接返回下標
}
}
return right;
}
};
69.x 的平方根 【找一個數】
大意:
實現 int sqrt(int x) 函式。
計算並返回 x 的平方根,其中 x 是非負整數。
由於返回型別是整數,結果只保留整數的部分,小數部分將被捨去。
樣例:
輸入: 8
輸出: 2
說明: 8 的平方根是 2.82842…,
由於返回型別是整數,小數部分將被捨去。
思路:相當於求x方 - a = 0的解。所以就是在[0,a]之間二分法找一個數可以x * x = a;
class Solution {
public:
int mySqrt(int a) {
if(a == 0 || a == 1) return a;
int n = a - 1;
int left = 1, right = a,sqrt;
while (left < right) //左閉右開
{
int mid = left + (right - left) / 2;
sqrt = a / mid;
if (sqrt == mid)
return mid;
else if (sqrt < mid) //目標值在左區間中,此時mid一定不是目標值
right = mid; //右邊是開區間
else
left = mid + 1; //左閉是閉區間,而Mid已經不是目標值了,所以要加一
}
return right-1; //退出時,左右重合
}
};
34.在排序陣列中查詢元素的第一個和最後一個位置 【區間查詢】
大意:
給定一個按照升序排列的整數陣列 nums,和一個目標值 target。找出給定目標值在陣列中的開始位置和結束位置。
如果陣列中不存在目標值 target,返回 [-1, -1]。
樣例:
輸入:nums = [5,7,7,8,8,10], target = 8
輸出:[3,4]
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if (nums.empty())
return vector<int>{-1, -1};
int lower = lower_bound(nums, target);
int high = high_bound(nums, target);
if (lower == nums.size() || nums[lower] != target) //沒有賦值的情況
return vector<int>{-1, -1};
return vector<int>{lower, high-1};
}
int lower_bound(vector<int>& nums,int target)
{
int l = 0, r = nums.size();
while (l < r)
{
int mid = l + (r - l) / 2;
if (nums[mid] < target)
l = mid + 1;
else if (nums[mid] >= target) //等於也要繼續往左邊找
r = mid;
}
return r; //左閉右開寫法,最後 跳出來l == r所以這裡寫l,r都可以
}
int high_bound(vector<int>& nums, int target) //尋找第一個大於target的數
{
int l = 0,r = nums.size();
while (l < r)
{
int mid = l + (r - l) / 2;
if (nums[mid] > target)
r = mid;
else
l = mid + 1; //如果相等也要往右邊找,因為要找到第一個大於Target的數
}
return r;
}
};
81. 搜尋旋轉排序陣列 II 【旋轉陣列】
大意:假設按照升序排序的陣列在預先未知的某個點上進行了旋轉。
( 例如,陣列 [0,0,1,2,2,5,6] 可能變為 [2,5,6,0,0,1,2] )。
編寫一個函式來判斷給定的目標值是否存在於陣列中。若存在返回 true,否則返回 false。
即給的陣列是由某個遞增陣列平移變形而來的。
輸入: nums = [2,5,6,0,0,1,2], target = 0
輸出: true
思路:二分時,先找確定的區間。如確定右邊是有序的,而且target又可以落入區間內,就先去右邊找target。在這裡要注意,target必須在有序的範圍內 (這裡上屆下屆都要寫,因為如果不寫,可能會漏查)。如果不在,就要到另一半區間去嘗試二分尋找。
如給陣列[3,1],和target = 3;
一開始判斷1是有序的遞增數列,如果不寫上界,就會直接結束程式,然而3是在mid的左邊。
class Solution {
public:
bool search(vector<int>& nums, int target) {
int left = 0, right = nums.size();
while (left < right)
{
int mid = left + (right - left) / 2;
if (nums[mid] == target)
return true;
if (nums[mid] == nums[left]) //沒法知道有序無序
++left;
else if (nums[mid] > nums[left]) //中間大於最左邊,說明左邊有序
{
if (nums[mid] > target && target >= nums[left]) //target落入左邊且大小合法
right = mid;
else
left = mid + 1;
}
else
{
int end = (right == nums.size() ? nums.size() - 1 : right);
if (nums[mid] < target && target <= nums[end])//target落入右邊且合法
left = mid + 1; // 如輸入[3, 1], target = 3
else
right = mid; //落入右邊但大小不合法,說不定在左邊可以找到,所以要去嘗試一下左邊
}
}
return false;
}
};
相關文章
- Python 二分查詢與 bisect 模組Python
- 查詢——二分查詢
- 二分查詢(一)——純粹的二分查詢
- 二分查詢
- Python查詢-二分查詢Python
- PHP二分查詢PHP
- 二分查詢法
- 二分插入與二分查詢
- 二分查詢 | 二分查詢的一種推薦寫法
- 查詢演算法__二分查詢演算法
- 順序查詢和二分查詢
- 二分查詢(c++)C++
- BinarySearch(二分查詢)
- 詳解二分查詢
- 704.二分查詢
- 查詢演算法之二分查詢演算法
- 二分查詢基礎專題——二分模板
- 【資料結構】折半查詢(二分查詢)資料結構
- leetcode -- 二分查詢LeetCode
- PHP 實現二分查詢PHP
- python二分查詢模板Python
- 二分查詢成長錄
- 圖解--二分查詢樹圖解
- 二分搜尋(折半查詢)
- 二分查詢的定義
- leetcode——二分查詢LeetCode
- 力扣之二分查詢力扣
- 二分查詢-不套用模板
- 二分查詢法小記
- 二分查詢演算法演算法
- 演算法->二分查詢演算法
- 【演算法】二分查詢演算法
- 7-1 二分查詢 (20分)
- 二分查詢【折半查詢】演算法 PHP 版演算法PHP
- Mysql查詢練習MySql
- Oracle_Day2 查詢練習,以及分頁Oracle
- MYSQL練習1: DQL查詢練習MySql
- 五、二分法查詢