1. 二分查找
LeetCode 704
题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
前提:
有序数组,且数组中无重复元素
易错点:
1.注意左右区间的开闭
2.更新left或者right时与middle的具体关系+1或-1
左闭右闭
注意点:
1.由于left和right都可以取得边界值,数组从0开始,因此将left赋值为0,而right赋值为n-1;
2.假设left和right都取1,左闭右闭成立,因此while循环中left<=right;
3.当if条件middle的值大于target,此时target肯定也不会取该middle(right取右闭),故right只能取到middle-1;当if条件middle的值小于target,此时target肯定也不会取该middle(left取左闭),故left只能取到middle+1。
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){
right = middle - 1;
}
else if(nums[middle] < target){
left = middle + 1;
}
else{
return middle;
}
}
return -1;
}
};
左闭右开
注意点:
1.由于left可以取边界,right不能取边界,数组从0开始,因此将left赋值为0,而right赋值为n;
2.假设left和right都取1,左闭右开显然不成立,因此while循环中left不能等于right,只能有left<right;
3.当if条件middle的值大于target,此时target肯定也不会取该middle(right取右开),right取到middle;当if条件middle的值小于target,此时target肯定也不会取该middle(left取左闭),故left只能取到middle+1。
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){
right = middle;
}
else if(nums[middle] < target){
left = middle + 1;
}
else{
return middle;
}
}
return -1;
}
};
tips:
防止溢出的写法:(两个int型变量相加可能会导致数组越界,但该题不会)
int middle = (left + right)/2;
改为
int middle = left + ((right - left)/2);
2. 移除元素
LeetCode 27
题目:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1: 给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
示例 2: 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
前提:
不要使用库函数,因为该题用库函数一步就解决了,而且erase是一个时间复杂度为O(n)的操作。
暴力法
解法:
两个for循环,当找到与目标值val相同的元素时,就将该元素之后的元素全都向前移动一位。
class Solution {
public:
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;
};
双指针法
解法:
1.用一个for循环完成了暴力法两个for循环实现的功能,采用快慢指针进行移动,快指针用来找目标值val;
2.当快指针没找到val时,将此时快指针的值赋给慢指针,然后快慢指针均向后移动;当快指针找到目标值val时,只有快指针向后移动;
3.最后循环完慢指针所指向的数组下标就是新数组的下标。
class Solution{
public:
int removeElement(vector<int>& nums, int val){
int slow = 0;
for(int fast = 0;fast < nums.size(); fast++){
if(val != nums[fast]){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
};