二分查找(上)
供自己记录用,如果错误 欢迎指正 小姐姐在此谢过
题目1283
这道题尝试了暴力解法,很明显会超时
首先给数组排个顺序,左界限为1,右边为最大的数,取中间数进行除法运算结果取上整,比较大小来决定下一次在哪个区间内进行判断。二分查找最容易出错的就是是否取等号的问题。
package bianry_search;import java.lang.reflect.Array;
import java.util.Arrays;
import javax.swing.text.StyleContext.SmallAttributeSet;
public class Solutio1283 {
public static void main(String[] args){
int[] nums = new int[]{2,3,5,7,11};
int threshold = 11;
int ans = new Solutio1283().smallestDivisor(nums, threshold);
System.out.print(ans);
}
//不采用二分查找的以下方法过于耗时
// public int SmallestDivisor(int[] nums,int threshold){
// int a = 1,b = threshold;
// int flag = 0;
// while(flag>b|flag==0){
// flag=0;
// for(int num:nums){
// double c = (double)num/(double)a;
// flag += Math.ceil(c);
System.out.print(c+" "+Math.ceil(c)+" ");
// }
// a++;
System.out.println(flag+" "+a);
// }
// return a-1;
// }
public static int smallestDivisor(int[] nums,int thresold){
if(nums.length<0){
return -1;
}
Arrays.sort(nums);
int left = 1,right = nums[nums.length-1];
while(left<right){
int mid=(left+right)/2;
int sum = 0;
for(int num:nums){
double a = (double)num/(double)mid;
sum += Math.ceil(a);//这里在进行处之前就需要进行强制转换了,不如可以直接判断好了
// if(mid != 0){
// if(num % mid == 0){
// sum += num / mid;
// }else{
// sum += num / mid + 1;
// }
// }
// System.out.print(a+" "+sum+" "+left+"-"+right+""+"\n");
}
if(sum < thresold)
right = mid;
else
left = mid+1;
}
return left;
}
}
class Solution {
public double myPow(double x,int n){
if(n ==0|x==1.0)
return 1.0;
if(x == 0.0)
return 0.0;
if(n < 0){
x = 1 / x;
n = -n;
}
double res = 1.0;
while(n !=0 ){
if((n & 1)==1){
res *= x;
}
x *=x;
n >>>= 1;
}
return res;
}
}
class Solution {
public int lengthOfLIS(int[] nums){
int len = nums.length;
if(len <= 0)
return 0;
if(len == 1)
return 1;
int[] tail = new int[len];
tail[0] = nums[0];
int end = 0;
for(int i = 1;i < len;i ++){
if(tail[end] < nums[i])
tail[++end] = nums[i];
else{
int left = 0;
int right = end;
while(left < right){
int mid = left + (right - left)/2;
if(tail[mid] < nums[i])
left = mid + 1;
else
right = mid;
}
tail[left] = nums[i];
}
}
return ++end;
}
}
这个理解了tail数组的含义就变得容易了.这个题可以有很多变形
马戏团人塔
俄罗斯套娃信封
对二维数组进行一个处理就可,然后求宽(体重)的最长上升子序列
Arrays.sort(envelopes,new Comparator<int[]>() {
public int compare(int[] a, int[] b){
return a[0]==b[0]?b[1]-a[1]:a[0]-b[0];
}
});