力扣 704 二分查找
题目:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-search
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解1:暴力解法
当我拿到这个题,不看数组中元素是否有序,直接在该数组中找到该元素,就直接一个for循环搞定,加上一个if判断语句,如果i对应的元素与target相等,输出i即可。
class Solution {
public:
int search(vector<int>& nums, int target) {
//暴力算法
for(int i = 0 ; i < nums.size(); i++){
if(nums[i] == target){
return i;
i++;
}
}
return -1 ;
}
};
题解2:carl哥解法 --要求是一个有序元素的整型数组
解法1:区间为左闭右开
这个地方要注意的是右边界,在while判断以及两个if判断结束后,左边界和右边界的取值问题,例如中间值大于目标值的时候,那么目标值是在左半区间,此时要考虑右边界的取值问题,但因为此题我们运用的是区间为左闭右开,那么右边界依然使用middle。但当中间值小于目标值时,目标值是在右半区间,左边界闭合,因此左边界我们的middle已经对比过了,不可能是目标值,所以此处左边界应该是middle+1.
class Solution {
public:
int search(vector<int>& nums, int target) {
//左闭右开区间 [left,right)
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 ;
}
};
解法2:区间为左闭右闭
这里我可以理解为区间左闭右闭,那么在中间值与目标值对比时,不管孰大孰小,左边界以及右边界都已经不是目标值了,此时我们均对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){
right = middle - 1;
}
else if(nums[middle] < target){
left = middle + 1;
}
else {
return middle;
}
}
return -1 ;
}
};
力扣 27 移除元素
题目:
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解1:暴力解法
拿到这个题,加上知道数组元素不能直接移除,而是需要覆盖的知识。想到使用两个for循环来解决这个问题,一层for循环来找到这个目标元素,再用一层for循环将此目标元素后面的元素进行前移一位,进行覆盖,从而达到移除题中目标元素的目的。
这里要注意:因为需要移除的目标元素可能不止一个,因此在里层for循环前移后,要对当前目标元素下标i进行前移一位操作(因为不前移一位的话,当前i指的就是后面元素前移过后的第一个元素,要是这个元素是目标元素呢?),数组整体长度也要减1。再进行后面的寻找-前移覆盖。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
//暴力解法--两个for循环
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 carl哥解法--双指针
利用一个for循环来达到两个for循环的效果,这里用到的就是快慢指针(SlowIndex 和 FastIndex)来做,精髓是if判断语句中的nums[fast] != val,轻松将目标值排除。
还有一个需要注意的点是:最后返回数组的新长度为什么是slow的值?
就是在最后一个快指针在老数组中找到非目标元素,将此元素赋值慢指针所在新数组,慢指针加一,但是后面没新元素输入到数组,又因为指针下标是从0开始,所以新数组的长度就是当前slow值。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
//双指针解法
int slow = 0 ;
for(int fast = 0 ;fast < nums.size() ; fast++){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++ ;
}
}
return slow ;
}
};