一:搜索二维矩阵
1. 两次查找
第一次在每行的第一个元素查找,然后在该行中查找
1 2 3 4 5 6 7 8 9 class Solution {public : bool searchMatrix (vector<vector<int >>& matrix, int target) { auto row = upper_bound (matrix.begin (), matrix.end (), target, [](int target, vector<int >& row){return target < row[0 ];}); if (row == matrix.begin ()) return false ; --row; return binary_search (row->begin (), row->end (), target); } };
2. 一次查找
将二位矩阵展开为一维,然后把索引转换为二维去处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution {public : bool searchMatrix (vector<vector<int >>& matrix, int target) { int row = matrix.size (); int col = matrix[0 ].size (); int left = 0 , right = row * col - 1 ; while (left <= right) { int mid = ((right - left) >> 1 ) + left; int cur = matrix[mid / col][mid % col]; if (cur > target) right = mid - 1 ; else if (cur < target) left = mid + 1 ; else return true ; } return false ; } };
二:在排序数组中查找元素的第一个和最后一个位置
1. 二分查找
先查找左边界,然后寻找右边界,最后验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution {public : vector<int > searchRange (vector<int >& nums, int target) { int left = BinarySearch (nums, target, true ); int right = BinarySearch (nums, target, false ) - 1 ; if (left >= 0 && left <= right && right < nums.size () && nums[left] == target && nums[right] == target) return vector<int >{left, right}; return vector<int >{-1 , -1 }; } int BinarySearch (vector<int >& nums, int target, int lowFlag) { int left = 0 ; int right = nums.size () - 1 ; int mid = 0 ; int ans = nums.size (); while (left <= right) { mid = (right - left) / 2 + left; if (nums[mid] > target || (nums[mid] >= target && lowFlag)) { right = mid - 1 ; ans = mid; } else left = mid + 1 ; } return ans; } };
三:搜索旋转排序数组
1. 二分查找
这题比普通的二分稍微复杂一些,主要在于取中间点后,中间点可能大于也可能小于起始元素,但有一边一定是有序的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution {public : int search (vector<int >& nums, int target) { int len = nums.size (); if (len == 0 ) return false ; if (len == 1 ) return target == nums[0 ] ? 0 : -1 ; int left = 0 , right = len - 1 ; int mid = 0 ; while (left <= right) { mid = (right - left) / 2 + left; if (nums[mid] == target) return mid; if (nums[0 ] <= nums[mid]) { if (nums[0 ] <= target && target < nums[mid]) right = mid - 1 ; else left = mid + 1 ; } else { if (nums[mid] < target && target <= nums[len - 1 ]) left = mid + 1 ; else right = right -1 ; } } return -1 ; } };
四:寻找旋转排序数组中的最小值
1. 二分查找
这题和上题类似,主要利用划分后最小值可能存在的位置,左边或者右边
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution {public : int findMin (vector<int >& nums) { int left = 0 ; int right = nums.size () - 1 ; int mid = 0 ; while (left < right) { mid = (right - left) / 2 + left; if (nums[mid] < nums[right]) right = mid; else left = mid + 1 ; } return nums[left]; } };
五:最小栈
1. 辅助栈
栈的实现可以直接使用stack,但这里需要记录最小值,并且常数查找,因此使用辅助栈来记录每一个元素对应的最小值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class MinStack { stack<int > value; stack<int > min; public : MinStack () { min.push (INT_MAX); } void push (int val) { value.push (val); min.push (std::min (val, min.top ())); } void pop () { value.pop (); min.pop (); } int top () { return value.top (); } int getMin () { return min.top (); } };