概述
二分查詢詳解.md
STL C++ 二分查詢庫
二分查詢庫
閉區間、左閉右開區間和開區間
影片講解二分法
class Solution {
// lower_bound 返回最小的滿足 nums[i] >= target 的 i
// 如果陣列為空,或者所有數都 < target,則返回 nums.size()
// 要求 nums 是非遞減的,即 nums[i] <= nums[i + 1]
// 閉區間寫法
int lower_bound(vector<int> &nums, int target) {
int left = 0, right = (int) nums.size() - 1; // 閉區間 [left, right]
while (left <= right) { // 區間不為空
// 迴圈不變數:
// nums[left-1] < target
// nums[right+1] >= target
int mid = left + (right - left) / 2;
if (nums[mid] < target)
left = mid + 1; // 範圍縮小到 [mid+1, right]
else
right = mid - 1; // 範圍縮小到 [left, mid-1]
}
return left; // 或者 right+1
}
// 左閉右開區間寫法
int lower_bound2(vector<int> &nums, int target) {
int left = 0, right = nums.size(); // 左閉右開區間 [left, right)
while (left < right) { // 區間不為空
// 迴圈不變數:
// nums[left-1] < target
// nums[right] >= target
int mid = left + (right - left) / 2;
if (nums[mid] < target)
left = mid + 1; // 範圍縮小到 [mid+1, right)
else
right = mid; // 範圍縮小到 [left, mid)
}
return left; // 或者 right
}
// 開區間寫法
int lower_bound3(vector<int> &nums, int target) {
int left = -1, right = nums.size(); // 開區間 (left, right)
while (left + 1 < right) { // 區間不為空
// 迴圈不變數:
// nums[left] < target
// nums[right] >= target
int mid = left + (right - left) / 2;
if (nums[mid] < target)
left = mid; // 範圍縮小到 (mid, right)
else
right = mid; // 範圍縮小到 (left, mid)
}
return right; // 或者 left+1
}
public:
vector<int> searchRange(vector<int> &nums, int target) {
int start = lower_bound(nums, target); // 使用其中一種寫法即可
if (start == nums.size() || nums[start] != target)
return {-1, -1};
// 如果 start 存在,那麼 end 必定存在
int end = lower_bound(nums, target + 1) - 1;
return {start, end};
}
};
作者:靈茶山艾府
連結:https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/solutions/1980196/er-fen-cha-zhao-zong-shi-xie-bu-dui-yi-g-t9l9/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
題目
34. 在排序陣列中查詢元素的第一個和最後一個位置
二分法寫作技巧:
1、首先 while (left <= right) 怎麼寫取決於,left right 是閉區間還是開區間。
2、mid = (left + right) / 2; 這個是不影響的,所有區間都這麼寫
3、將三種方法寫全,不要偷懶 。一開始我的 == 情況沒有分開寫導致了一大堆的問題
使用 STL 庫
vector<int> searchRange(vector<int> &nums, int target) {
auto bound = equal_range(nums.begin(), nums.end(), target);
int left = bound.first - nums.begin();
int right = bound.second - nums.begin();
return {left, right};
}
我的解題思路
我的思路:
1、尋找第一個小於。當等於的時候,繼續往左移。而不是 直接退出。知道找到最左一個滿足條件的值
2、尋找第一個大於,跟1一樣。
我的程式碼
#include "vector"
#include "set"
#include "iostream"
#include "algorithm"
#include "tuple"
#include "unordered_map"
using namespace std;
class Solution {
public:
// 找到左邊第一個
int find_first(vector<int> &nums, int target) {
int result = -1;
int left = 0;
int right = nums.size() - 1;
int mid = 0;
while (left <= right) { // 在閉區間之中尋找 [left, right]
mid = (left + right) / 2;
if (nums[mid] == target){
result = mid;
right = mid -1 ; // 當找到一個時,繼續往左邊尋找
}else if (nums[mid] > target) {
right = mid -1 ;
} else if (nums[mid] < target) {
left = mid + 1;
}
}
return result;
}
// 找到右邊最後一個
int find_last(vector<int> &nums, int target) {
int result = -1;
int left = 0;
int right = nums.size() - 1;
int mid = 0;
while (left <= right) {
mid = (left + right) / 2;
if (nums[mid] == target){
result = mid;
left = mid + 1;
}else if (nums[mid] > target) {
right = mid -1;
} else if (nums[mid] < target) {
left = mid + 1;
}
}
return result;
}
vector<int> searchRange(vector<int> &nums, int target) {
int left = find_first(nums, target);
int right = find_last(nums, target);
if (nums.size() == 0 || left > right) {
return {-1, -1};
}
return {left, right};
}
};
int main() {
std::cout << "Hello, World!" << std::endl;
Solution *a = new Solution();
vector<int> nums = {5, 7, 7, 8, 8, 10};
a->searchRange(nums, 8);
return 0;
}
704. Binary Search 704. 二分查詢 🟢
我的解題思路和程式碼
1、一個簡單的二分查詢
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
int mid = 0;
while (left <= right) {
mid = (left + right) / 2;
if (nums[mid] == target){
return mid;
}else if (nums[mid] > target) {
right = mid -1 ;
} else if (nums[mid] < target) {
left = mid + 1;
}
}
return -1;
}
};
使用STL庫
#include "algorithm"
int searchRange(vector<int> &nums, int target) {
auto it = lower_bound(nums.begin(), nums.begin() + nums.size()-1, target);
int left = it - nums.begin();
return left;
}
劍指 Offer 53 - I. 在排序陣列中查詢數字 I
我的解題思路和程式碼:
1、用二分法找到第一個滿足條件的值
2、然後用一次遍歷找到所有的值
class Solution {
public:
// 找到左邊第一個
int find_first(vector<int> &nums, int target) {
int left = 0;
int right = nums.size() - 1;
int mid = 0;
int result = -1;
while (left <= right) {
mid = (left + right) / 2;
if (nums[mid] == target){
result = mid;
right = mid-1;
}else if (nums[mid] > target) {
right = mid -1 ;
} else if (nums[mid] < target) {
left = mid + 1;
}
}
return result;
}
int search(vector<int>& nums, int target) {
int result = 0;
int left = find_first(nums, target);
if(left==-1){
return 0;
}
while (left<nums.size() && nums[left]==target){
left++;
result += 1;
}
return result;
}
};
官網題解
1、找到左右兩邊的值,然後取差值