二分查找刷题
704. 二分查找
1.左闭右闭写法
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right){
//mid = (left + right )/2 = left + (right - left)/2,注意!!!位运算的优先级要比+号低
int mid = left + (right - left) >> 1;
if(target > nums[mid]) left = mid + 1;
else if(target < nums[mid]) right = mid - 1;
else return mid;
}
//在循环结束(即left > right时)时还没return,说明没找到
return -1;
}
}
2.左闭右开写法(右开值其实等于右闭值再加1,参考那些数组长度循环判断)
class Solution {
public int search(int[] nums, int target) {
int left = 0, 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;
}
}
34. 在排序数组中查找元素的第一个和最后一个位置
思路:因为有序,target在数组中有两种情况:
1.数组中存在target,那么找到的左右边界长度要大于等于1
2.数组中找不到,有三种情况:
2.1.这个数比区间中任何一个数还小
2.2.这个数比区间中任何一个数还大
2.3这个数在左右区间之间,但是不存在,也就是说左右边界的差,要小于等于0
class Solution {
public int[] searchRange(int[] nums, int target) {
int leftBound = getLeftBound(nums, target);
int rightBound = getRightBound(nums, target);
if(leftBound == -2 || rightBound == -2){
return new int[]{-1,-1};
}
if(rightBound - leftBound > 1){
return new int[]{leftBound + 1, rightBound - 1};
}
return new int[]{-1,-1};
}
private int getRightBound(int[] nums, int target){
int left = 0, right = nums.length - 1;
int rightBound = -2;
while(left <= right){
int mid = left + ((right - left) >> 1);
if(nums[mid] > target) right = mid - 1;
else{
left = mid + 1;
rightBound = left;
}
}
return rightBound;
}
private int getLeftBound(int[] nums, int target){
int left = 0, right = nums.length - 1;
int leftBound = -2;
while(left <= right){
int mid = left + ((right - left) >> 1);
if(nums[mid] < target){
left = mid + 1;
}else{
right = mid - 1;
leftBound = right;
}
}
return leftBound;
}
}
69. x 的平方根
本题用二分查找,mid的平方是必须小于等于x的,对比上题,发现本质上就是在求右边界(也就是收缩左区间时)。
class Solution {
public int mySqrt(int x) {
int left = 0, right = x, ans = -1;
while(left <= right){
int mid = left + ((right - left) >> 1);
if((long) mid * mid <= x){
ans = mid;
left = mid + 1;
}else{
right = mid - 1;
}
}
return ans;
}
}
367. 有效的完全平方数
把上面的69题算出的最大算数平方根的方法拿来用就好了
class Solution {
public boolean isPerfectSquare(int num) {
int sqrt = sqrt(num);
return sqrt * sqrt == num;
}
private int sqrt(int num){
int left = 0, right = num, ans = -1;
while(left <= right){
int mid = left + ((right - left) >> 1);
if((long)mid * mid <= num){
ans = mid;
left = mid + 1;
}else{
right = mid - 1;
}
}
return ans;
}
}