代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素。
今日任务
数组理论基础,704. 二分查找,27. 移除元素
1数组理论基础
文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
- 数组内存空间的地址是连续的
2 704. 二分查找
题目链接:https://leetcode.cn/problems/binary-search/
文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html
视频讲解:https://www.bilibili.com/video/BV1fA4y1o715
情况1
target 是在一个在左闭右闭的区间里,也就是[left, right]。
- while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
- if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length -1;
while (left <= right){
int mid = left + (right - left)/2;
if(target < nums[mid]){
right = mid -1;
}else if(target > nums[mid]){
left = mid + 1;
}else{
return mid;
}
}
return -1;
}
}
情况2
定义 target 是在一个在左闭右开的区间里,也就是[left, right) ,那么二分法的边界处理方式则截然不同。
有如下两点:
- while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
- if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length;
while (left < right){
int mid = left + ((right - left)>>1);
if(target < nums[mid]){
right = mid;
}else if(target > nums[mid]){
left = mid + 1;
}else{
return mid;
}
}
return -1;
}
}
left + ((right -left) >> 1) == (left + right) /2
>>: 二进制右移
举个例子: 1010 >> 1 == 0101
1010 十进制 10
0101 十进制 5
综上 >> 1 作用相当于除二
所以 left + ((right -left) >> 1) ==> left + ((right -left)/2)
==> left + right/2 -left/2 ==> left/2 + right/2 ==> (left + right) /2
总结
搞清楚边界的定义,循环中注意边界值的变化;
3 27. 移除元素
题目建议: 暴力的解法,可以锻炼一下我们的代码实现能力,建议先把暴力写法写一遍。 双指针法 是本题的精髓,今日需要掌握,至于拓展题目可以先不看。
题目链接:https://leetcode.cn/problems/remove-element/
文章讲解:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html
视频讲解:https://www.bilibili.com/video/BV12A4y1Z7LP
3.1 暴力循环
class Solution {
public int removeElement(int[] nums, int val) {
int len = nums.length;
for(int i = 0;i< len;i ++){
if(nums[i] == val){
for(int j = i +1;j< len;j ++){
nums[j-1] = nums[j];
}
len --;
i--;
}
}
return len;
}
}
时间复杂度是O(n^2)
3.2双指针法
双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢指针
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置
class Solution {
public int removeElement(int[] nums, int val) {
int slow = 0;
for(int fast = 0;fast < nums.length;fast ++){
if (val != nums[fast]){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)
第一天总结:
逐渐回忆之前的知识(数组特点+双指针),以及用java解答问题。用时2.5h,希望之后加快速度。

浙公网安备 33010602011771号