================
- 2026/07/20新补充
- 记住一点即可:
二分法是找到第一个大于等于target的位置
while(left <= right) { int mid = (left + right)/2; int x = nums[mid]; if(x >= target){ ans = mid; r = mid - 1; }else l = mid +1; } return ans;- 比如说这个例子:
35. 搜索插入位置
1)如果什么方法都不用,直接暴力去算:
class Solution { public: //找到第一个大于等于target的位置 int searchInsert(vector<int>& nums, int target) { int n = nums.size(); for(int i = 0 ; i < n ; i++) { if(nums[i] >= target)return i; } return n; } };2)如果使用二分
class Solution { public: //找到第一个大于等于target的位置 int searchInsert(vector<int>& nums, int target) { int n = nums.size(); int ans = n; int l = 0 , r = n-1; while(l <= r) { int mid = (l + r)/2; int x = nums[mid]; if(x >= target) { ans = mid; r = mid - 1; }else { l = mid + 1; } } return ans; } };================
先说体会:
二分法中,无论是r=mid-1,还是l=mid+1;都说明mid不是我们要的答案,所以我们不要它,将它减去,或者略过。
如果是l=mid或者r=mid,说明mid还有用
以下为两个重要模板
二分法其实是不断逼近x,我们假设q[ ]数组是从小到大排列的
模板1:
while(l<r){intmid=l+r>>1;if(q[mid]>=x)r=mid;//这个r可以用来求出来的是>=x的最小值(优先求出)elsel=mid+1;}//如果不存在>=x的最小值,这个r求出来的是<=x的最大值(其次求出)模板2
while(l<r){intmid=l+r+1>>1;if(q[mid]<=x)l=mid;//这个l可以用来求出来的是<=x的最大值(优先求出)elser=mid-1;}//如果不存在<=x的最大值,这个l求出来的是>=x的最小值(其次求出)2022-11-20的力扣320场周赛的第二题,完美的使用了以上的模板
6242. 二叉搜索树最近节点查询
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */classSolution{public:vector<vector<int>>closestNodes(TreeNode*root,vector<int>&queries){if(!root)return{{-1,-1}};vector<int>v;vector<vector<int>>ans;queue<TreeNode*>q;q.push(root);//下面这个while循环就是宽搜框架while(q.size()){intlen=q.size();//这个一层的元素个数for(inti=0;i<len;i++){autot=q.front();//每次拿到这个一行的第i个元素v.push_back(t->val);q.pop();//接下来,我们来扩展一下队列,为下一层宽搜作准备if(t->left)q.push(t->left);if(t->right)q.push(t->right);}}sort(v.begin(),v.end());//我们模拟的单调队列for(inti=0;i<queries.size();i++){intl=0,r=v.size()-1;//队头和队尾while(l<r){//求>=queries[i]的最小值intmid=l+r>>1;if(v[mid]>=queries[i])r=mid;elsel=mid+1;}inttmp=r;l=0,r=v.size()-1;//队头和队尾while(l<r){//求<=queries[i]的最大值intmid=l+r+1>>1;if(v[mid]<=queries[i])l=mid;elser=mid-1;}intleft=v[l],right=v[tmp];if(v[tmp]<queries[i])right=-1;if(v[l]>queries[i])left=-1;ans.push_back({left,right});}returnans;}};再来一题
AcWing 789. 数的范围(算法基础课)
再来一题
LeetCode 33. 搜索旋转排序数组(LeetCode究极班)
再来一题
6367. 求出最多标记下标
再来一题
AcWing 1236. 递增三元组
补充