leetcode704.二分查找
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回
示例 1:
输入:nums
= [-1,0,3,5,9,12],target
= 9 输出: 4 解释: 9 出现在nums
中并且下标为 4
示例 2:
输入:nums
= [-1,0,3,5,9,12],target
= 2 输出: -1 解释: 2 不存在nums
中因此返回 -1
解这道题,首先需要确定的是区间。区间就是你需要遍历的范围
我们一般使用以下两种区间
左闭右闭[left,right]
左闭右开[left,right)
之后,有很多人在做二分查找题目时会有两个疑问:
第一:while循环的条件是什么是while(left<right)还是while(left<=right)
第二:一次查找结束后,mid是应该mid-1/mid+1又或者是让right=mid/left=mid
由这两个问题,可以引出两个解法,也会就是上面所说的左闭右闭,左闭右开
左闭右闭代码如下
int search(vector<int>& nums, int target) {
int left = 0,right = nums.size()-1;
while(left <= right){//使用=是因为可以遍历最右边的数据
int mid = (left+right)/2;
if(target < nums[mid]){
right = mid-1;//使用mid-1是因为,mid已经被遍历,不是需要的数据,所以使用mid-1
}
else if(target > nums[mid]){
left = mid+1;//同上
}else return mid;
}
return -1;
}
左闭右开代码如下
int search(vector<int>& nums, int target) {
int left = 0,right = nums.size();//因为右边为开区间,不会遍历最右边的元素,所以不用减一
while(left < right){//因为不遍历最右边的元素,并且需要判断,所以mid不减一
int mid = (left+right)/2;
if(target < nums[mid]){
right = mid;
}
else if(target > nums[mid]){
left = mid+1;
}else return mid;
}
return -1;
}
LeetCode27.移除元素
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
这道题可以使用暴力解法进行求解,使用双层for循环即可。第一层循环遍历所有元素,在找到需要移除的元素后,进行第二层遍历,进行移除操作。再将之后的元素都依次向前移动即可。
暴力求解代码如下
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
for(int i = 0;i < size;i++){
if(nums[i] == val){
for(int j = i+1;j < size;j++){
nums[j-1] = nums[j];
}
i--;
size--;
}
}
return size;
}
使用暴力求解的时间复杂度是O(N^2),可以引入双指针的思想进行求解
我们定义两个指针,一个快指针,一个慢指针
快指针fastPoint:用于确定新数组的元素值,也就是不等于目标元素的数组元素
慢指针slowPoint:用于确定心数组的下标位置。。
明白了双指针的作业,我们就将快指针指向的元素加入到慢指针指向1元素下标中即可。
双指针代码如下
int removeElement(vector<int>& nums, int val) {
int fastPoint=0;//用于获取新数组中的元素,即在arr中不等于val的数组元素
int slowPoint=0;//用于确定新数组1下标值,即在快指针获取到元素后应放在新数组的哪个下标
for(;fastPoint<nums.size();fastPoint++){
if(nums[fastPoint] != val){
nums[slowPoint] = nums[fastPoint];
slowPoint++;
}
}
return slowPoint;
}