今日任务
数组理论基础,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,希望之后加快速度。
标签:27,target,nums,int,随想录,middle,right,移除,left From: https://www.cnblogs.com/gaoyuan2lty/p/16896149.html