前言
参加了卡哥的算法训练营班,今天是第一天,主要是了解掌握二分双指针。
因为有点基础所以做的时候比较轻松,从今天开始坚持
一、二分
704. 二分查找
题目链接: LeetCode 704 二分查找
文章讲解:卡哥二分讲解
视频讲解:b站视频
状态:A了
思路:题目讲的很明白了,是二分查找,所以直接上手二分解
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1, ans = -1;
while (l < r) {
int m = (l + r) / 2;
if (nums[m] < target) {
l = m + 1;
} else if (nums[m] > target) {
r = m - 1;
} else {
return m;
}
}
return ans;
}
};
- 未通过
上面是自己手搓出来的二分,能过题目的测试案例,但是提交的时候出错了
思考一下为什么
这跟下面左闭右闭AC的代码很相似,
区别只在于
while(l < r)
与
while (l <= r)
-左闭右闭-
- 这里应该使用 l<=r,因为left == right是有意义的,所以使用 <=
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1, ans = -1;
while (l <= r) {
int m = (l + r) / 2;
if (nums[m] < target) {
l = m + 1;
} else if (nums[m] > target) {
r = m - 1;
} else {
return m;
}
}
return ans;
}
};
- 时间复杂度:O(nlogn)
- 空间复杂度:O(1)
-左闭右开-
附上左闭右开代码,看完卡哥讲解后自己手写了一遍
-
这里 while (l < r),这里使用 < ,因为l == r在区间[l, r)是没有意义的
-
r 更新为 m,因为当前nums[m]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以r更新为m
即:下一个查询区间不会去比较nums[m]
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() , ans = -1;
while (l < r) {
int m = (l + r) / 2;
if (nums[m] < target) {
l = m + 1;
} else if (nums[m] > target) {
r = m ;
} else {
return m;
}
}
return ans;
}
};
- 时间复杂度:O(nlogn)
- 空间复杂度:O(1)
二、双指针
27. 移除元素
题目链接: LeetCode 27 移除元素
文章讲解:卡哥双指针讲解
视频讲解:b站视频.
状态:A了
之前有点算法基础,就没用暴力
Debug了一下,自己一次双指针过了
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n=nums.size();
int slow=-1,fast=0;
while(fast<n){
if(slow<fast && nums[fast]!=val){
slow++;
nums[slow]=nums[fast];
}
fast++;
}
return slow+1;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
主要是fast用来遍历数组,slow用来修改数组
同时返回的数组长度就等于slow遍历的长度
总结
今天学习比较的轻松,时间1~2h左右
巩固了一遍双指针和二分,挺有收获的