初始条件:有序数组
1.二分查找
class Solution {
public int search(int[] nums, int target) {
int left=0; int right =nums.length-1;
while (left<=right) {
int mid=(left+right)/2;
if (nums[mid]<target) left=mid+1;
if (nums[mid]>target) right=mid-1;
if (nums[mid]==target) return mid ;
}
return-1;
}
}
2.搜索插入位置
class Solution {
public int searchInsert(int[] nums, int target) {
int left=0; int right =nums.length-1;
while (left<right) { //没有等号
int mid=(left+right)/2;
if (nums[mid]<target) left=mid+1;
if (nums[mid]>target) right=mid-1;
if (nums[mid]==target) return mid ;
}
return nums[left]>=target?left:(left+1); //有等号
}
}
3.猜数字大小
public class Solution extends GuessGame {
public int guessNumber(int n) {
int left = 1, right = n;
while (left < right) { // 循环直至区间左右端点相同
int mid = left + (right - left) / 2; // 防止计算时溢出
if (guess(mid) <= 0) {
right = mid; // 答案在区间 [left, mid] 中
} else {
left = mid + 1; // 答案在区间 [mid+1, right] 中
}
}
// 此时有 left == right,区间缩为一个点,即为答案
return left;
}
}
4.x 的平方根
class Solution {
public int mySqrt(int x) {
int l = 0, r = x, ans = -1;
while (l <= r) {
int mid = l + (r - l) / 2; //防止溢出
if ( mid * mid <= x) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
return ans;
}
}
5.两数之和 II - 输入有序数组
空间复杂度O(1)
class Solution {
public int[] twoSum(int[] numbers, int target) {
int l=0, r=numbers.length-1;
while (l<r) {
if (numbers[l]+numbers[r]<target) { //有序的,类似滑动窗口
l++;
}else if (numbers[l]+numbers[r]>target) {
r--;
}else return new int[]{l+1,r+1};
}
return new int[]{-1,-1};
}
}
6. 在 D 天内送达包裹的能力
求船的最低载重
重点确定 二分查找的 左右边界
class Solution { public int shipWithinDays(int[] weights, int days) { // 定义左边界,最小运载力为包裹最重者 int L =Arrays.stream(weights).max().getAsInt(); // 定义右边界,最大运载力为所有包括重量之和,1天搞定 int R =Arrays.stream(weights).sum(); // 二分查找 while (L<R) { int need=1,cur=0; // 所需天数,与第i天的载重量cur int mid=L+(R-L)/2; for (int weight : weights) { //计算mid载重下的所需天数 if (cur + weight > mid) { ++need; cur = 0; } cur += weight; } if (need<=days) { //比较mid载重下的天数,来查找载重范围 R=mid; }else { L=mid+1; } } return L; } }
补充:Arrays.stream()用法
求数组最大值、最小值、总和、平均值
static int [] intArr = new int[]{30,96,23,69,85,62,12,99,11};
public static void main(String[] args) {
IntStream intStream =Arrays.stream(intArr);
int sum = intStream.sum();
intStream =Arrays.stream(intArr);
int max = intStream.max().getAsInt();
intStream =Arrays.stream(intArr);
int min = intStream.min().getAsInt();
intStream =Arrays.stream(intArr);
double avg = intStream.average().getAsDouble();
System.out.println("最大值:"+max+"\n最小值:"+min+"\n总和:"+sum+"\n平均值:"+avg);
}
7.第一个错误的版本
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int l =1;
int r =n;
while(l<r){
int mid = l+(r-l)/2;
if(!isBadVersion(mid)){
l = mid+1;
}else{
r = mid;
}
}
return l;
}
}