二分查找(704)
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-search
1.1暴力
class solution{
public:
int search(vector<int>& nums,int target){
for(int i=0;i<nums.size();i++)
{
if(nums[i]==targrt)
return i;
}
return -1;//为什么
}
};
1.2 二分法做题
什么是二分法,无非就是一半一半分,即middle=(left+right)/2,到底割去那一半,留下那一半,就要看我们找的目标值target和nums[middle]进行比较:
num[middle]>target :考虑左区间[left,middle]
num[middle]<target : 考虑右区间[midlle,right]
num[middle]=target : 找到了,返回middle
采用二分法需要注意的问题
第一点:设置left和right时要么采用左闭右闭的形式:[left,right]
要么采用左闭右开的形式:[left,right)
第二点:什么条件下进入循环,即:while(left<=right) 还是 while(left<rigth)
如果是采用左闭右闭的形式:[left,right],即定义的时候:int left=0;int right=nums.size()-1;
while(left<=right) 取等号是有意义的
num[middle]>target :考虑左区间[left,middle-1]
num[middle]<target : 考虑右区间[midlle+1,right]
num[middle]=target : 找到了,返回middle
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size()-1;
while(left<=right)
{
int middle=(left+right)/2;
if(nums[middle]<target)
{
left=middle+1;
}
else if(nums[middle]>target)
{
right=middle-1;
}
else
{
return middle;
}
}
return -1;
}
};
如果是采用左闭右开的形式:[left,right), 即定义的时候:int left=0;int right=nums.size();
while(left<rigth) 取等号没有意义
num[middle]>target :考虑左区间[left,middle)
num[middle]<target : 考虑右区间[midlle+1,right)
num[middle]=target : 找到了,返回middle
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size();
while(left<right)
{
int middle=(left+right)/2;
if(nums[middle]<target)
{
left=middle+1;
}
else if(nums[middle]>target)
{
right=middle;
}
else
{
return middle;
}
}
return -1;
}
};
移除元素(27)
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);
在函数里修改输入数组对于调用者是可见的。
根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
链接:https://leetcode.cn/problems/remove-element
2.1暴力
数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖
一个for循环遍历数组元素 ,第二个for循环更新数组
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len=0;
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;
}
};
2.2双指针法
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢指针
快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
慢指针:指向更新新数组下标的位置
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowly=0;
for(int fast=0;fast<nums.size();fast++)
{
if(nums[fast]!=val)
{
nums[slowly]=nums[fast];
slowly++;
}
}
return slowly;
}
};