本系列目的在于跟练代码随想录,以及记录自己在数据结构与算法方面的一些学习
704.二分查找
其实之前自己在随便刷题的时候看过这道题目,就是一个纯新手的大状态,第一次听到二分查找这样的东西,然后跟着题解自己敲出来了,今天再做的时候觉得还是关于搜索边界方面还是定义不清晰,始终没有办法对搜索边界有个很清楚的一个认知。所以今天再做还是有些磕绊
下面是今天的代码
1.左闭右闭
class Solution {
public:
int search(vector<int>& nums, int target) {
int l=0,r = nums.size()-1;
while(l<=r){
int mid = (l+r)/2;
if(target>nums[mid]){
l = mid+1;
}else if(target<nums[mid]){
r = mid-1;
}else{
return mid;
}
}
return -1;
}
};
左闭右闭,在每次搜索新的区间的时候,我们当前的target已经确定不在目前的区间中,所以更改区间边界的时候要mid+1/mid-1;在确定循环条件这里,左闭右闭即[1,1]这样是满足条件的,所以是l<=r.
2.左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
int l=0,r = nums.size();
while(l<r){
int mid = (l+r)/2;
if(target>nums[mid]){
l = mid+1;
}else if(target<nums[mid]){
r = mid;
}else{
return mid;
}
}
return -1;
}
};
27.移除元素
在此就不对题目进行重复的描述了
本题的关键在于理解数组的底层机制,了解数组删除元素之后其实是后续元素对当前元素的覆盖,而并不是直接删除,可以用暴力解法和双指针法进行求解,其中双指针法更加关键,能够很大程度上降低问题的复杂度,关于双指针发在carl哥的视频里讲解的比较清楚
1.暴力解法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n = nums.size();
for(int i=0;i<n;++i){
if(nums[i]==val){
for(int j =i+1;j<n;++j){
nums[j-1] = nums[j];
}
i--;
n--;
}
}
return n;
}
};
这里i--很好理解,可以画图来帮助理解[1,2,3,5,3,6]自己对着这个数组画一下图就ok了
2.双指针法
还有快慢指针的办法,这个和我之前看的视频解法不一样
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;
}
};
规定了一个快指针一个慢指针,快指针指向了非需要删除的元素,慢指针指向了我们假想的新数组,实际就是在旧的数组上进行更改,这里刚开始不太好理解,就是把新数组放在旧数组上,每次遇到一个想要的值,就记录数值,即为fast指针,slow指针指向新数组需要存放的位置,每次村过来新数字之后slow指针就指向下一个位置。