题目:
34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)
需要知识:
数组:对于java的数组来说,内存管理是交给虚拟机管理的,地址是虚拟地址
数组初始化:int[] nums = {0,....,0};、int[] nums = new int[size];
数组方法:nums.length
二分法:对于已经排序好的数组有效
参考资料:代码随想录 (programmercarl.com)
1.二分查找一个数:
代码:
要点:要有边界值的概念,如果left=0,right=长度,这说明包括两个指针在内的值都有可能是target
所以whlie的条件是left<=right
class Solution {
public int search(int[] nums, int target) {
//左边从数组下标0开始
int begin = 0;
//右边从数组中最后一位数开始
int end = nums.length - 1;
//获取数组中间下标,因为mid的更新依赖于begin和end
int mid = (begin + end) / 2;
//进入循环,因为在边界上也可能存在target(由begin和end从哪里开始决定)
while (begin <= end){
//进入左边
if(target < nums[mid]){
end = mid - 1;
mid = (begin + end) / 2;
//进入右边
} else if(target > nums[mid]){
begin = mid + 1;
mid = (begin + end) / 2;
//找到了
} else{
return mid;
}
}
return -1;
}
}
2.二分查找到合适的位置(从左到右)
要点:一:对于target在数组中的情况,mid最后总会在left位置上(三种情况:mid 直接等于target不说、target在left边界上,数组长度为奇数则mid和left和right在同一位置上,数组长度为偶数则mid和left在同一位置上,right在left+1);二:对于没有target在数组中的情况(总之就是left和right会把target本应该在的位置夹住):1.left会先和right地址相差一位,2.接着mid会和他们地址相等,3.接着right会往左一个而跳出循环,所以最后mid和left的位置相同,在大于target的最小一个数的地址,
(原因:1.是向下取整,所以就算target在right边界上,right也会不断的等left抵达它的位置)
class Solution {
public int searchInsert(int[] nums, int target) {
int begin = 0;
int end = nums.length - 1;
//为了不再一次调用nums.length函数,就这样写了
int result = end + 1;
while(begin <= end){
int mid = (begin + end) / 2;
if(target <= nums[mid]){
result = mid;
end = mid - 1;
}else {
begin = mid + 1;
}
}
return result;
//return end + 1;return begin;一样的效果
}
}
3.双指针
要点:要想象有一只章鱼,他的头是慢指针,触手是快指针
class Solution {
public int removeElement(int[] nums, int val) {
// 快慢指针
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
}
4.总结:思想都理解,但实际上手还是生疏,为了不知其然不知其所以然,花费了一番力气