二分查找
题目链接:704.二分查找
解题思路:弄清楚二分法的核心思想,明确区间的定义(左闭右闭or左闭右开),视为不变量,进而确定while()循环条件是否需要带等号和if()条件判断后区间边界的赋值。
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right){
int middle = left + right >> 1;
if(nums[middle] > target){
right = middle - 1;
}else if(nums[middle] < target){
left = middle + 1;
}else{
return middle;
}
}
return -1;
}
}
注意:当nums[middle] = target时,返回middle,即target在数组中的位置。不能写在if-else的条件判断外面,否在在第一次循环中,即使条件不满足也会直接返回,就不符合题意了。
拓展题
题目链接:35. 搜索插入位置
区别:target不一定在原数组中,最后不满足while(left <= right)时,即left>right时,返回的是应该是left或者是right+1。
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right){
int middle = left + right >> 1;
if(nums[middle] < target){
left = middle + 1;
}else if(nums[middle] > target){
right = middle - 1;
}else{
return middle;
}
}
return left;
}
}
区别:数组中元素会有重复,需要找到起始和终止target的位置,可以先找到>=target的第一个位置,再找target和target+1起始位置。注意返回的值。
class Solution {
public int[] searchRange(int[] nums, int target) {
int left = search(nums,target);
int right = search(nums,target + 1);
// 如果left最后到了末尾或者左索引位置的值不等于target时,说明没有找到对应的target值
if(left == nums.length || nums[left] != target){
return new int[]{-1,-1};
}
return new int[]{left,right-1};
}
// 找到>=target的第一个位置
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right){
int middle = left + right >> 1;
if(nums[middle] < target){
left = middle + 1;
}else if(nums[middle] >= target){
right = middle - 1;
}
}
return left;
}
}
移除元素
题目链接:27. 移除元素
解题思路:双指针法, 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
慢指针:指向更新 新数组下标的位置
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];
}
}
return slowIndex;
}
}