704.二分查找
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 if(nums[mid]<target){
left=mid+1;
}
}
return -1;
}
}
注意:指针所指区间为左闭右闭区间,故循环终止条件为left>right。与mid所指元素比较后,右指针要-1。循环结束后仍未找到,返回-1。
可以优化的地方:mid=left+(right-left)/2,防止溢出。
class Solution {
public int search(int[] nums, int target) {
// 二分查找法。利用左闭右开区间
int left=0,right=nums.length;
while(left<right){
int mid=left+(right-left)/2;
if(nums[mid]==target){
return mid;
}else if(nums[mid]>target){
right=mid;
}else if(nums[mid]<target){
left=mid+1;
}
}
return -1;
}
}
35.搜索插入位置
题目链接:
class Solution {
public int searchInsert(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 if(nums[mid]<target){
left=mid+1;
}
}
return left;
}
}
二分查找后的left即是应该插入的位置
34.在排序数组查找重复元素的索引
题目链接:34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)
class Solution {
public int[] searchRange(int[] nums, int target) {
// 二分查找法
int left=0,right=nums.length-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]==target){
int[] res=new int[2];
int start=mid,end=mid;
while(start>=0&&nums[start]==target){
start--;
}
while(end<nums.length&&nums[end]==target){
end++;
}
res[0]=start+1;
res[1]=end-1;
return res;
}else if(nums[mid]>target){
right=mid-1;
}else if(nums[mid]<target){
left=mid+1;
}
}
return new int[]{-1,-1};
}
}
时间复杂度为O(logn+n)。
简化
class Solution {
public int[] searchRange(int[] nums, int target) {
// 利用二分查找函数
int leftIdx=binarySearch(nums,target,true);
int rightIdx=binarySearch(nums,target,false)-1;
if(leftIdx<=rightIdx&&rightIdx<nums.length&&nums[leftIdx]==target&&nums[rightIdx]==target){
return new int[]{leftIdx,rightIdx};
}
return new int[]{-1,-1};
}
public int binarySearch(int[] nums,int target,boolean lower){
// ans在leftidx第一个等于target的数,在right中第一个不等于的索引
int left=0,right=nums.length-1,ans=nums.length;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]>target||(lower&&nums[mid]>=target)){
right=mid-1;
ans=mid;
}else{
left=mid+1;
}
}
return ans;
}
}
27.移除元素
class Solution {
public int removeElement(int[] nums, int val) {
// 快慢指针
int slow=0,fast=0;
while(fast<nums.length){
if(nums[fast]!=val){
nums[slow]=nums[fast];
slow++;
}
fast++;
}
return slow;
}
}
心得:利用快慢指针。之后考虑什么时候移动慢指针、快指针、循环结束条件。
循环结束条件:fast要遍历数组所有元素。
移动快指针:每循环一次fast++。
移动慢指针:当快指针所指元素不是val时,将该元素移动到slow指针上,slow++。