力扣704.二分查找
思路:在二分查找的过程中,循环不变量原则,要搞清楚边界定义,我习惯用左闭右闭的区间。
C++代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size()-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]<target){
left=mid+1;
}
else if(nums[mid]>target){ //if和else if执行是互斥的
right=mid-1;
}
else
return mid;
}
return -1;
}
};
力扣27.移除元素
思路:双指针法回顾,分别定义快慢指针,快指针遍历整个数组,寻找不含有需要删除的元素的新数组,慢指针就是用来指向更新后的新数组
C++代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowindex=0;
for(int fastindex=0;fastindex<nums.size();fastindex++){
if(val!=nums[fastindex]){
nums[slowindex]=nums[fastindex];
slowindex++;
}
}
return slowindex;
}
};
力扣35.搜索插入位置
题目链接:35. 搜索插入位置 - 力扣(LeetCode)
思路:由于本道题目要求的特殊性,nums为无重复元素的升序数组,只需要查找数组中第一个大于等于目标元素的下标位置即可,所以使用暴力法遍历整个数组效率很高。另一种方法还是使用二分法,中间条件判断与704题类似,我习惯按照左闭右闭区间,最后返回值需要考虑到四种情况。
C++代码:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left=0;
int right=nums.size()-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]>target){
right=mid-1;
}
else if(nums[mid]<target){
left=mid+1;
}
else return mid;
}
// 分别处理如下四种情况
// 目标值在数组所有元素之前 [0, -1]
// 目标值等于数组中某一个元素 return middle;
// 目标值插入数组中的位置,return right + 1
// 目标值在数组所有元素之后的情况 , 因为是右闭区间,所以 return right + 1
return right+1;
}
};
力扣34.在排序数组中查找元素的第一个和最后一个位置
题目链接:34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)
思路:本质还是二分查找,只不过由于数组中存在相同的元素,需要找出相同元素的起始位置和结束位置。构造两个函数分别确定左边界和右边界。(找target的右边界时,而left=mid+1,是往右移动的,然后下次移动是在target大于等于mid位置的元素时候,以此类推,直到退出循环)
C++代码:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int rBorder=getRightBorder(nums,target);
int lBorder=getLeftBorder(nums,target);
// 情况一 target在数组范围的左边或右边
if (lBorder == -2 || rBorder == -2) return {-1, -1};
// 情况三 target在数组中
if (rBorder - lBorder > 1) return {lBorder + 1, rBorder - 1};
// 情况二 target在数组范围内,但没有相同元素
return {-1, -1};
}
private:
int getRightBorder(vector<int>&nums,int target){
int left=0;
int right=nums.size()-1;
int rBorder=-2;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]>target){
right=mid-1;
}
else{
left=mid+1;
rBorder=left;
}
}
return rBorder;
}
int getLeftBorder(vector<int>&nums,int target){
int left=0;
int right=nums.size()-1;
int lBorder=-2;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]>=target){
right=mid-1;
lBorder=right;
}
else{
left=mid+1;
}
}
return lBorder;
}
};