LeetCode 704. Binary Search
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right){
int mid = left + (right - left) / 2;
if(nums[mid] == target){
return mid;
}
else if(nums[mid] > target){
right = mid - 1;
}
else{
left = mid + 1;
}
}
return -1;
}
}
有序数组查找问题,优先想到二分查找。
搜索一个元素时,搜索区间两端闭(左闭右闭),初始化为int left = 0, right = nums.length - 1,while条件带等号(<=),if相等就返回,更新时在mid基础上必须加减1,while结束后return -1;。
搜索左右边界时,左闭右开(最常用),初始化为int left = 0, right = nums.length;,while要用小于号(<),if相等别返回,利用mid锁边界,更新时在mid基础上是left = mid + 1和right = mid, while结束(left == right)后,搜索左侧边界返回return left;,搜索右侧边界返回return left - 1;(right - 1 也是一样的)。
参考资料:labuladong的算法小抄
拓展题
34. Find First and Last Position of Element in Sorted Array
class Solution {
public int[] searchRange(int[] nums, int target) {
return new int[]{searchLeft(nums, target), searchRight(nums,target)};
}
private int searchLeft(int[] nums, int target){ // 搜索左侧边界
int left = 0, right = nums.length - 1;
// 搜索区间[left, right]
while(left <= right){
int mid = left + (right - left) / 2;
if(nums[mid] < target){
left = mid + 1;
}
else if(nums[mid] > target){
right = mid - 1;
}
else if(nums[mid] == target){ // 收缩右侧边界
right = mid - 1;
}
}
// 检查出界情况
if(left >= nums.length || nums[left] != target){
return -1;
}
return left;
}
private int searchRight(int[] nums, int target){ // 同样道理搜索右侧边界
int left = 0, right = nums.length - 1;
while(left <= right){
int mid = left + (right - left) / 2;
if (nums[mid] < target){
left = mid + 1;
}
else if(nums[mid] > target){
right = mid - 1;
}
else if(nums[mid] == target){
left = mid + 1;
}
}
if(right < 0 || nums[right] != target){
return -1;
}
return right;
}
}
class Solution {
public int searchInsert(int[] nums, int target) {
/**
二分搜索的目标是寻找第一个不小于 target 的元素的位置。
如果 target 大于数组中所有的元素,那么应该返回的位置就是数组的长度,也就是 nums.length。
因此,我们需要将搜索的范围设置为 [0, nums.length]。
*/
int left = 0, right = nums.length;
while(left < right){
int mid = left + (right - left) / 2;
if(nums[mid] == target){
right = mid;
}
else if(nums[mid] < target){
left = mid + 1;
}
else{
right = mid;
}
}
return left;
}
}
LeetCode 27. Remove Element
class Solution {
public int removeElement(int[] nums, int val) {
int slow = 0, fast = 0;
// 以下处理完后,所有nums中不等于val的元素都在nums的开头slow个位置,slow的大小即为这个nums中不等于val的元素的个数
while(fast < nums.length){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
fast++; // 当fast所指位置nums[fast]等于val时则只有fast++
}
return slow;
}
}
由于题目要求原地修改数组,所以用双指针,想到这个方法之后就比较简单了。