数组专项
二分查找
二分查找解题模板
int binary_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) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if(nums[mid] == target) {
// 直接返回
return mid;
}
}
// 直接返回
return -1;
}
int left_bound(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) {
// 别返回,锁定左侧边界
right = mid - 1;
}
}
// 判断 target 是否存在于 nums 中
// 此时 target ⽐所有数都⼤,返回 -1
if (left == nums.length) return -1;
// 判断⼀下 nums[left] 是不是 target
return nums[left] == target ? left : -1;
}
int right_bound(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;
}
}
// 此时 left - 1 索引越界
if (left - 1 < 0) return -1;
// 判断⼀下 nums[left] 是不是 target
return nums[left - 1] == target ? (left - 1) : -1;
}
一.704. 二分查找
int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length - 1; // 注意 是最后一个元素的索引
while(left <= right) {
int mid = left + (right - left) / 2;
if(nums[mid] == target)
return mid;
//去搜索区间 [left, mid-1] 或者区间 [mid+1, right] ,因为 mid 已经搜索过,应该从搜索区间中去除。
else if (nums[mid] < target)
left = mid + 1; // 注意
else if (nums[mid] > target)
right = mid - 1; // 注意
}
return -1;
}
二.34. 在排序数组中查找元素的第一个和最后一个位置
class Solution {
public int[] searchRange(int[] nums, int target) {
return new int[]{left_bound(nums,target),rigth_bound(nums,target)};
}
public int left_bound(int[] nums,int target){
int left=0;
int 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 if(nums[mid]==target){
right=mid;
}
}
if(left==nums.length) return -1;
return nums[left]==target?left:-1;
}
public int rigth_bound(int[] nums,int target){
int left=0;
int right=nums.length;
while(left<right){
int mid=left+(right-left)/2;
if(nums[mid]<target){
left=mid+1;
}else if(nums[mid]>target){
right=mid;
}else if(nums[mid]==target){
left=mid+1;
}
}
if(left-1<0) return -1;
return nums[left-1]==target?left-1:-1;
}
}
三.35. 搜索插入位置
class Solution {
public int searchInsert(int[] nums, int target) {
int left=0;
int 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){
return mid;
}
}
//注意
return left;
}
}
四.74. 搜索二维矩阵
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m=matrix.length,n=matrix[0].length;
int left=0,right=m*n-1;
while(left<=right){
int mid=left+(right-left)/2;
if(get(matrix,mid)>target){
right=mid-1;
}else if(get(matrix,mid)<target){
left=mid+1;
}else if(get(matrix,mid)==target){
return true;
}
}
return false;
}
//通过一维坐标访问二维数组中的值
int get(int[][] matrix, int index){
int m=matrix.length,n=matrix[0].length;
int i=index/n,j=index%n;
return matrix[i][j];
}
}
五. 392. 判断子序列
class Solution {
public boolean isSubsequence(String s, String t) {
int i=0;
int j=0;
while(i<s.length()&&j<t.length()){
if(s.charAt(i)==t.charAt(j)){
i++;
}
j++;
}
return i==s.length();
}
}
六.69. x 的平方根
class Solution {
public int mySqrt(int x) {
// 特殊值判断
if (x == 0) {
return 0;
}
if (x == 1) {
return 1;
}
int left=1;
int right=x/2;
while(left<=right){
int mid=left+(right-left)/2;
if(mid==x/mid){
return mid;
}else if(mid>x/mid){
right=mid-1;
}else if(mid<x/mid){
left=mid+1;
}
}
return left-1;
}
}
七.367. 有效的完全平方数
class Solution {
public boolean isPerfectSquare(int num) {
if (num == 0) {
return true;
}
if (num == 1) {
return true;
}
int left=1;
int right=num/2;
while(left<=right){
int mid=left+(right-left)/2;
long square = (long) mid * mid;
if(square==num){
return true;
}else if(square<num){
left=mid+1;
}else if(square>num){
right=mid-1;
}
}
return false;
}
}
八.875. 爱吃香蕉的珂珂
class Solution {
public int minEatingSpeed(int[] piles, int h) {
int maxVal=0;
for (int pile : piles) {
maxVal = Math.max(maxVal, pile);
}
int left=1;
int right=maxVal;
while(left<right){
int mid=left+(right-left)/2;
if(f(piles,mid)<=h){
right=mid;
}else{
left=mid+1;
}
}
return right;
}
int f(int[] piles,int x){
int hours=0;
for(int i=0;i<piles.length;i++){
hours+=piles[i]/x;
if(piles[i]%x>0){
hours++;
}
}
return hours;
}
}