D1: 为什么报这个群呢,之前一直很难坚持,我觉得还是报个群,然后大家一起写,一起打卡会坚持住。没有自制力,再没有一起写的朋友的话,真的可以躺平了-.-
704.Binary Search:题目还是很简单的,二分查找,属于是自己写会写,但是会有小细节漏下。重点是左闭右开还是左闭右闭。详细见下
//递归写法
class Solution {
public:
int search(vector<int>& nums, int target,int low,int high) {
if(low>high) return -1;
int mid=low+(high-low)/2;
if(nums[mid]==target) return mid;
if(nums[mid]>target) {
high=mid-1;
return search(nums, target, low, high);
}else{
low=mid+1;
return search(nums, target, low, high);
}
}
};
递归写法,先确定确定递归函数,返回值以及参数,然后确定递归终止条件,如果是左闭右开,就要改成
if(low>=high) return -1;
最后是单层递归的逻辑,也就是target在哪边查哪边。
下面是迭代法:
//迭代法
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.empty()) return -1;
int low=0;
int high=nums.size()-1;
while(low<=high){
int mid=low+(high-low)/2;
if(nums[mid]==target) return mid;
else if(nums[mid]>target){
high=mid-1;
}else{
low=mid+1;
}
}
return -1;
}
};
左闭右闭写法的话,[low,high]是有效的,所以while后面是可以low<=high的,如果是左闭右开,就不能<=了,因为[low,high)无效。相应的,下面的low和high也要对应-1,+1。
27. Remove Element
暴力解法:
// 时间复杂度:O(n^2)
// 空间复杂度:O(1)
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;
}
};
然后是双指针法,快指针指向整个数组,慢指针记录新数组的长度。
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;
}
看了代码随想录的文章后,还有一种相向双指针法,改变了元素相对位置,确保了移动最少元素。
int removeElement(vector<int>& nums, int val) {
int slow=0;
int fast=nums.size()-1;
while(slow<=fast){
while(slow<=fast && nums[slow]!=val){
++slow;
}
while(slow<=fast && nums[fast]==val){
--fast;
}
if (slow < fast) {
nums[slow++] = nums[fast--];
}
}
return slow;
}
总结:双指针法的使用要强化一下,然后对于适用场景,比如数组场景要更加熟悉;数组使用时的边界条件要多加判断。