二分查找
检查一个数是否在数组中占绝大多数
class Solution {
public int leftest(int[] nums,int target){
int left=0,right=nums.length-1;
int mid=0;
while(left<right){
mid=left+((right-left)>>1);
if(nums[mid]>=target){
right=mid;
}
else{
left=mid+1;
}
}
return left;
}
public int rightest(int[] nums,int target){
int left=0,right=nums.length-1;
int mid=0;
while(left<right){
mid=left+((right-left)>>1);
if(nums[mid]>target){
right=mid;
}
else{
left=mid+1;
}
}
return left;
}
public boolean isMajorityElement(int[] nums, int target) {
//二分找出等于target最左的位置
int left=leftest(nums,target);
//二分找出等于target最右的位置
int right=rightest(nums,target);
if(left==right){
return false;
}
return right-left+1>nums.length/2;
}
}
不动点
class Solution {
public int fixedPoint(int[] arr) {
int left=0,right=arr.length-1;
int mid=0;
while(left<right){
mid=left+((right-left)>>1);
if(arr[mid]==mid){
right=mid;
}else if(arr[mid]<mid){
left=mid+1;
}else{
right=mid-1;
}
}
return left==arr[left]?left:-1;
}
}
猜数字大小
/**
* Forward declaration of guess API.
* @param num your guess
* @return -1 if num is lower than the guess number
* 1 if num is higher than the guess number
* otherwise return 0
* int guess(int num);
*/
public class Solution extends GuessGame {
public int guessNumber(int n) {
int left=1,right=n;
int mid=0;
while(left<=right){
mid=left+((right-left)>>1);
if(guess(mid)==0)return mid;
else if(guess(mid)>0){
left=mid+1;
}else{
right=mid-1;
}
}
return left;
}
}
第 k 个缺失的正整数
class Solution {
public int findKthPositive(int[] arr, int k) {
int left=0,right=arr.length-1;
if(arr[arr.length-1]==arr.length)return arr[arr.length-1]+k;
if(arr[0]-1>=k){
return k;
}else{
k-=(arr[0]-1);
}
int mid=0;
while(left<right){
mid=left+((right-left)>>1);
if(left==mid)break;
//if(k==0)break;
else if(arr[mid]-arr[left]-(mid-left)>0){
if(arr[mid]-arr[left]-(mid-left)<k){
k-=arr[mid]-arr[left]-(mid-left);
left=mid;
}else{
right=mid;
}
}else{
left=mid;
}
}
if(left<arr.length-1){
if(arr[left]+1==arr[left+1]){
return arr[arr.length-1]+k;
}else{
return arr[left+1]-arr[left]-1>=k?arr[left]+k:arr[left+1]+(k-(arr[left+1]-arr[left]-1));
}
}
return arr[left]+k;
}
}
找出数组排序后的目标下标
class Solution {
public int leftest(int[] nums,int target){
int left=0,right=nums.length-1;
int mid=0;
while(left<right){
mid=left+((right-left)>>1);
if(nums[mid]<target){
left=mid+1;
}else{
right=mid-1;
}
}
return left;
}
public int rightest(int[] nums,int target){
int left=0,right=nums.length-1;
int mid=0;
while(left<right){
mid=left+((right-left)>>1);
if(nums[mid]<=target){
left=mid+1;
}else{
right=mid-1;
}
}
return left;
}
public List<Integer> targetIndices(int[] nums, int target) {
Arrays.sort(nums);
//二分找出等于target最左的位置
int left=leftest(nums,target);
//二分找出等于target最右的位置
int right=rightest(nums,target);
List<Integer>list=new ArrayList<>();
for(int i=left;i<=right;++i){
if(nums[i]==target){
list.add(i);
}
}
return list;
}
}
早餐组合
class Solution {
//O(NlogN)
public int breakfastNumber(int[] staple, int[] drinks, int x) {
//排序
Arrays.sort(staple);
Arrays.sort(drinks);
int ans=0;
int index=0;
for(int s=0;s<staple.length;++s){
if(staple[s]>=x)break;
int rest=x-staple[s];
//二分查找drinks数组中大于rest的最左的位置
index=getIndex(drinks,rest);
if(rest<drinks[index]){
ans+=index;
}else{
ans+=index+1;
}
ans%=1000000007;
}
return ans%1000000007;
}
public int getIndex(int[] drinks,int x){
int left=0,right=drinks.length-1;
int mid=0;
while(left<right){
mid=left+((right-left)>>1);
if(drinks[mid]>x){
right=mid-1;
}else{
left=mid+1;
}
}
return left;
}
}
第一个错误的版本
/* The isBadVersion API is defined in the parent class VersionControl.
boolean isBadVersion(int version); */
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int left=1,right=n;
int mid=0;
while(left<=right){
mid=left+((right-left)>>1);
if(isBadVersion(mid)){
right=mid-1;
}else{
left=mid+1;
}
}
return left;
}
}
采购方案
class Solution {
//先排序再二分
public int fun(int[] nums,int target){
Arrays.sort(nums);
int ans=0;
for(int i=0;i<nums.length-1;++i){
if(nums[i]>=target)break;
//二分找到比target-nums[i]大的最左位置
int index=getIndex(nums,target-nums[i],i+1,nums.length-1);
if(target-nums[i]>=nums[index]){
ans+=(index-i);
}else{
ans+=(index-i-1);
}
ans%=1000000007;
}
return ans%1000000007;
}
public int getIndex(int[] nums,int x,int left,int right){
if(left==right)return left;
int mid=0;
while(left<right){
mid=left+((right-left)>>1);
if(nums[mid]>x){
right=mid-1;
}else{
left=mid+1;
}
}
return left;
}
public int purchasePlans(int[] nums, int target) {
// return process(nums,0,2,target);
// return DP(nums,target);
return fun(nums,target);
}
}
和为s的两个数字
class Solution {
public int index(int[] nums,int x,int left,int right){
int mid=0;
while(left<right){
mid=left+((right-left)>>1);
if(nums[mid]==x)return mid;
else if(nums[mid]<x){
left=mid+1;
}else{
right=mid-1;
}
}
return left;
}
public int[] twoSum(int[] nums, int target) {
int[] ans=new int[2];
for(int i=0;i<nums.length-1;++i){
int cur=index(nums,target-nums[i],i+1,nums.length-1);
if(target-nums[i]==nums[cur]){
ans[0]=nums[i];
ans[1]=target-nums[i];
break;
}
}
return ans;
}
}
排序数组中两个数字之和
class Solution {
public int index(int[] numbers,int x,int left,int right){
int mid=0;
while(left<right){
// System.out.println(left+" "+right);
mid=left+((right-left)>>1);
if(numbers[mid]==x)return mid;
else if(numbers[mid]<x){
left=mid+1;
}else{
right=mid-1;
}
}
return left;
}
public int[] twoSum(int[] numbers, int target) {
int[] ans=new int[2];
int cur=0;
for(int i=0;i<numbers.length-1;++i){
cur=index(numbers,target-numbers[i],i+1,numbers.length-1);
if(numbers[cur]==target-numbers[i]){
ans[0]=i;
ans[1]=cur;
break;
}
}
return ans;
}
}
查找插入位置
class Solution {
public int searchInsert(int[] nums, int target) {
int left=0,right=nums.length-1;
int mid=0;
while(left<=right){
mid=left+((right-left)>>1);
if(nums[mid]==target)return mid;
else if(nums[mid]<target){
left=mid+1;
}else{
right=mid-1;
}
}
return left;
}
}
山峰数组的顶部
class Solution {
//O(N)解法
public int process1(int[] arr){
for(int i=0;i<arr.length-1;++i){
if(arr[i]>arr[i+1]){
return i;
}
}
return 0;
}
//O(longN)解法
//二分查找
public int process2(int[] arr){
int left=0,right=arr.length-1;
int mid=0;
while(left<=right){
mid=left+((right-left)>>1);
if(mid==0){
left=mid+1;
}
else if(mid==arr.length-1){
right=mid-1;
}
else if(arr[mid]>arr[mid-1]&&arr[mid]>arr[mid+1]){
return mid;
}else if(arr[mid]>arr[mid-1]&&arr[mid]<arr[mid+1]){
left=mid+1;
}else{
right=mid-1;
}
}
return 0;
}
public int peakIndexInMountainArray(int[] arr) {
// return process1(arr);
return process2(arr);
}
}
求平方根
class Solution {
public int mySqrt(int x) {
if(x==0||x==1)return x;
long left=1,right=x/2;
long mid=left+((right-left)>>1);
while(left<=right){
mid=left+((right-left)>>1);
if(mid*mid==x){
break;
}
else if(mid*mid<x){
if((mid+1)*(mid+1)>x)break;
left=mid+1;
}
else{
right=mid-1;
}
}
return (int)mid;
}
}
最接近的二叉搜索树值
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int closestValue(TreeNode root, double target) {
TreeNode cur=root;
int ans=0;
double min=Integer.MAX_VALUE;
while(cur!=null){
if(min>=Math.abs(cur.val-target)){
min=Math.abs(cur.val-target);
ans=cur.val;
}
if(target<cur.val){
cur=cur.left;
}else{
cur=cur.right;
}
}
return ans;
}
}