二分查找
hot100_34.在排序數組中查找元素的第一個和最后一個位置
給你一個按照非遞減順序排列的整數數組 nums
,和一個目標值 target
。請你找出給定目標值在數組中的開始位置和結束位置。
如果數組中不存在目標值 target
,返回 [-1, -1]
。
你必須設計并實現時間復雜度為 O(log n)
的算法解決此問題。
示例 1:
輸入:nums = [5,7,7,8,8,10], target = 8
輸出:[3,4]
示例 2:
輸入:nums = [5,7,7,8,8,10], target = 6
輸出:[-1,-1]
示例 3:
輸入:nums = [], target = 0
輸出:[-1,-1]
#include<iostream>
#include<vector>
using namespace std;class Solution {
public:int search(vector<int>& nums, float target){int l = 0, r = nums.size()-1;while(l <= r){int m = (r + l)/2;if(nums[m] > target) r = m - 1;else l = m + 1;}return l;}vector<int> searchRange(vector<int>& nums, int target) {int left = search(nums, float(target - 0.5));int right = search(nums, float(target + 0.5)) - 1;
// cout << left << " " <<right << endl;if(left <= right) return {left, right};else return {-1, -1}; }
};int main(){vector<int> nums = {5,6,6,8,8,9};int target = 7;Solution A;vector<int> ans = A.searchRange(nums, target);cout << ans[0] << " " << ans[1] << endl;return 0;
}
hot100_33.搜索旋轉排序數組
整數數組 nums
按升序排列,數組中的值 互不相同 。
在傳遞給函數之前,nums
在預先未知的某個下標 k
(0 <= k < nums.length
)上進行了 旋轉,使數組變為 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]
(下標 從 0 開始 計數)。例如, [0,1,2,4,5,6,7]
在下標 3
處經旋轉后可能變為 [4,5,6,7,0,1,2]
。
給你 旋轉后 的數組 nums
和一個整數 target
,如果 nums
中存在這個目標值 target
,則返回它的下標,否則返回 -1
。
你必須設計一個時間復雜度為 O(log n)
的算法解決此問題。
示例 1:
輸入:nums = [4,5,6,7,0,1,2], target = 0
輸出:4
示例 2:
輸入:nums = [4,5,6,7,0,1,2], target = 3
輸出:-1
示例 3:
輸入:nums = [1], target = 0
輸出:-1
#include<iostream>
#include<vector>
using namespace std;class Solution {
public:int search(vector<int>& nums, int target) {int l = 0, r = nums.size() - 1;while (l <= r) {int mid = (l + r) / 2;if(nums[mid] == target) return mid;// nums[lo] > target: 目標值小于左邊界// nums[lo] > nums[mid]: 左邊界大于中間值,說明左半部分是無序的// target > nums[mid]: 目標值大于中間值// 這三個條件的異或結果決定了目標值應該在左半部分還是右半部分if ((nums[l] > target) ^ (nums[l] > nums[mid]) ^ (target > nums[mid]))l = mid + 1;elser = mid;}return -1;}
};int main(){
// vector<int> nums = {4,5,6,7,0,1,2};
// int target = 0;
// vector<int> nums = {3,5,1};
// int target = 3;vector<int> nums = {5,1,3};int target = 5;Solution A;int ans = A.search(nums, target);cout << ans << endl;return 0;
}
hot100_153.尋找旋轉排序數組中的最小值
已知一個長度為 n
的數組,預先按照升序排列,經由 1
到 n
次 旋轉 后,得到輸入數組。例如,原數組 nums = [0,1,2,4,5,6,7]
在變化后可能得到:
-
若旋轉
4
次,則可以得到
[4,5,6,7,0,1,2]
-
若旋轉
7
次,則可以得到
[0,1,2,4,5,6,7]
注意,數組 [a[0], a[1], a[2], ..., a[n-1]]
旋轉一次 的結果為數組 [a[n-1], a[0], a[1], a[2], ..., a[n-2]]
。
給你一個元素值 互不相同 的數組 nums
,它原來是一個升序排列的數組,并按上述情形進行了多次旋轉。請你找出并返回數組中的 最小元素 。
你必須設計一個時間復雜度為 O(log n)
的算法解決此問題。
示例 1:
輸入:nums = [3,4,5,1,2]
輸出:1
解釋:原數組為 [1,2,3,4,5] ,旋轉 3 次得到輸入數組。
示例 2:
輸入:nums = [4,5,6,7,0,1,2]
輸出:0
解釋:原數組為 [0,1,2,4,5,6,7] ,旋轉 4 次得到輸入數組。
示例 3:
輸入:nums = [11,13,15,17]
輸出:11
解釋:原數組為 [11,13,15,17] ,旋轉 4 次得到輸入數組。
class Solution {
public:int findMin(vector<int>& nums) {int low = 0;int high = nums.size() - 1;while (low < high) {int pivot = (low + high) / 2;if (nums[pivot] < nums[high]) high = pivot ;else low = pivot + 1;}return nums[low];}
};
hot100_4.尋找兩個正序數組的中位數、
給定兩個大小分別為 m
和 n
的正序(從小到大)數組 nums1
和 nums2
。請你找出并返回這兩個正序數組的 中位數 。
算法的時間復雜度應該為 O(log (m+n))
。
示例 1:
輸入:nums1 = [1,3], nums2 = [2]
輸出:2.00000
解釋:合并數組 = [1,2,3] ,中位數 2
示例 2:
輸入:nums1 = [1,2], nums2 = [3,4]
輸出:2.50000
解釋:合并數組 = [1,2,3,4] ,中位數 (2 + 3) / 2 = 2.5
class Solution {
public:int getKthElement(const vector<int>& nums1, const vector<int>& nums2, int k) {int m = nums1.size();int n = nums2.size();int index1 = 0, index2 = 0;while (true) {// 邊界情況if (index1 == m) {return nums2[index2 + k - 1];}if (index2 == n) {return nums1[index1 + k - 1];}if (k == 1) {return min(nums1[index1], nums2[index2]);}// 正常情況int newIndex1 = min(index1 + k / 2 - 1, m - 1);int newIndex2 = min(index2 + k / 2 - 1, n - 1);int pivot1 = nums1[newIndex1];int pivot2 = nums2[newIndex2];if (pivot1 <= pivot2) {k -= newIndex1 - index1 + 1;index1 = newIndex1 + 1;}else {k -= newIndex2 - index2 + 1;index2 = newIndex2 + 1;}}}double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {int totalLength = nums1.size() + nums2.size();if (totalLength % 2 == 1) {return getKthElement(nums1, nums2, (totalLength + 1) / 2);}else {return (getKthElement(nums1, nums2, totalLength / 2) + getKthElement(nums1, nums2, totalLength / 2 + 1)) / 2.0;}}
};