二分难题 && deque

141. Sqrt(x)

https://www.lintcode.com/problem/sqrtx/description?_from=ladder&&fromId=4

public class Solution {
    /**
     * @param x: An integer
     * @return: The sqrt of x
     */
    public int sqrt(int x) {
        // write your code here
        if(x==0){
            return 0;
        }
        
        long start =1;
        long end = x;
        
        while(start+1<end){
            long mid = start+(end-start)/2;
            if(mid*mid<x){
                start = mid;
            }else{
                end = mid;
            }
        }
        
        if(end*end<=x){
            return (int)end;
        }
        
        return (int)start;
    }
}
View Code

 

586. Sqrt(x) II

https://www.lintcode.com/problem/sqrtx-ii/description?_from=ladder&&fromId=4

public class Solution {
    /**
     * @param x: a double
     * @return: the square root of x
     */
    public double sqrt(double x) {
        // write your code here
        double start =0;
        //如果x<1,那么右边界=1
        double end = Math.max(1,x);
        double diff = 1e-12;
        
        while(start+diff<end){
            double mid = start +(end-start)/2;
            if(mid*mid<x){
                start = mid;
            }else{
                end = mid;
            }
        }
        
        return start;
    }
}
View Code

 

390. Find Peak Element II

https://www.lintcode.com/problem/find-peak-element-ii/description?_from=ladder&&fromId=4

public class Solution {
    /*
     * @param A: An integer matrix
     * @return: The index of the peak
     */
    public List<Integer> findPeakII(int[][] A) {
        // write your code here
        if(A==null|| A.length==0|| A[0].length==0){
            return new ArrayList<>();
        }
        
        int r = A.length;
        int c = A[0].length;
        
        int low =1;
        int high = r-2;
        List<Integer> ans = new ArrayList<>();
        
        while(low<=high){
            int mid = low +(high-low)/2;
            int col = maxForEachRow(mid,A);
            if(A[mid][col]<A[mid-1][col]){
                high = mid-1;
            }else if(A[mid][col]<A[mid+1][col]){
                low = mid+1;
            }else{
                ans.add(mid);
                ans.add(col);
                break;
            }
            
        }
        
        return ans;

    }
    
    private int maxForEachRow(int row,int[][] A){
        int col = 0;
        int max = A[row][0];
        for(int i=0;i<A[row].length;i++){
            if(A[row][i]>max){
                max = A[row][i];
                col = i;
            }    
        }
        
        return col;
    }
}
View Code

 

183. Wood Cut

https://www.lintcode.com/problem/wood-cut/description?_from=ladder&&fromId=4

public class Solution {
    /**
     * @param L: Given n pieces of wood with length L[i]
     * @param k: An integer
     * @return: The maximum length of the small pieces
     */
    public int woodCut(int[] L, int k) {
        // write your code here
        if(L==null ||L.length ==0){
            return 0;
        }
        
        int l =0;
        int r =0;
        for(int len:L){
            r= Math.max(r,len);
        }
        
        while(l+1<r){
            int mid = l+ (r-l)/2;
            if(count(mid,L)>=k){
                l = mid;
            }else{
                r = mid;
            }
        }
        
        if(count(r,L)>=k){
            return r;
        }
        
        return l;
    }
    
    public int count(int len,int[] L){
        int sum =0;
        for(int wood:L){
            sum+=wood/len;
        }
        
        return sum;
    }
}
View Code

 

437. Copy Books

https://www.lintcode.com/problem/copy-books/description?_from=ladder&&fromId=4

public class Solution {
    /**
     * @param pages: an array of integers
     * @param k: An integer
     * @return: an integer
     */
    public int copyBooks(int[] pages, int k) {
        // write your code here
        if(pages==null || pages.length==0){
            return 0;
        }
        
        int start = getMaxPages(pages);
        int end = getTotalPages(pages);
        
        while(start+1<end){
            int mid = start + (end-start)/2;
            if(countPeople(pages,mid)<=k){
                end = mid;
            }else{
                start = mid;
            }
        }
        
        if(countPeople(pages,start)<=k){
            return start;
        }
        return end;
    }
    
    public int getTotalPages(int[]pages){
        int sum =0;
        for(int i =0;i<pages.length;i++){
            sum+=pages[i];
        }
        return sum;
    }
    
    public int getMaxPages(int[] pages){
        int max =0;
        for(int i=0;i<pages.length;i++){
            max = Math.max(max,pages[i]);
        }
        return max;
    }
    
    public int countPeople(int[] pages,int min){
        int count =0;
        int sum = 0;
        for(int i =0;i<pages.length;i++){
            if(sum+pages[i]>min){
                count++;
                sum = pages[i];
            }else{
                sum+=pages[i];
            }
        }
        if(sum>0){
            count++;
        }
        return count;
    }
}
View Code

 

438. Copy Books II

https://www.lintcode.com/problem/copy-books-ii/description?_from=ladder&&fromId=4

public class Solution {
    /**
     * @param n: An integer
     * @param times: an array of integers
     * @return: an integer
     */
    public int copyBooksII(int n, int[] times) {
        // write your code here
        if(times==null || times.length==0){
            return 0;
        }
        
        int start = getMin(times);
        int end = start*n;
        
        while(start+1<end){
            int mid = start +(end-start)/2;
            if(canCopy(times,n,mid)){
                end = mid;
            }else{
                start = mid;
            }
        }
        
        if(canCopy(times,n,start)){
            return start;
        }
        
        return end;
        
    }
    
    public int getMin(int[] times){
        int min = Integer.MAX_VALUE;
        for(int t:times){
            min = Math.min(t,min);
        }
        return min;
    }
    
    public boolean canCopy(int[] times,int n,int time){
        int sum = 0;
        for(int t:times){
            sum += time/t;
        }
        
        return sum>=n;
    }
}
View Code

 

414. Divide Two Integers

https://www.lintcode.com/problem/divide-two-integers/description?_from=ladder&&fromId=4

1. 基本思想是不断地减掉除数,直到为0为止。但是这样会太慢。

2. 我们可以使用2分法来加速这个过程。不断对除数*2,直到它比被除数还大为止。加倍的同时,也记录下cnt,将被除数减掉加倍后的值,并且结果+cnt。

因为是2倍地加大,所以速度会很快,指数级的速度。

3. 另外要注意的是:最小值的越界问题。对最小的正数取abs,得到的还是它。。。 因为最小的正数的绝对值大于最大的正数(INT)

所以,我们使用Long来接住这个集合就可以了。

public class Solution {
    /**
     * @param dividend: the dividend
     * @param divisor: the divisor
     * @return: the result
     */
    public int divide(int dividend, int divisor) {
        // Note: 在这里必须先取long再abs,否则int的最小值abs后也是原值
        long a = Math.abs((long)dividend);
        long b = Math.abs((long)divisor);
        
        long ret =0;
         // 这里必须是= 因为相等时也可以减
        while(a>=b){
            for(long deduce = b,cnt=1;deduce<=a;deduce<<=1,cnt<<=1){
                a = a-deduce;
                ret+=cnt;
            }
        }
        
        // 获取符号位。根据除数跟被除数的关系来定
        // bug 4: out of range:
         /*
         Input:    -2147483648, -1
         Output:    -2147483648
         Expected:    2147483647
         */
         ret = ((dividend > 0) ^ (divisor > 0)) ? -ret: ret;
         //另一种写法
         //ret = ((((dividend ^ divisor) >> 31) & 1) == 1) ? -ret: ret;
         
         if (ret > Integer.MAX_VALUE || ret < Integer.MIN_VALUE) {
             return Integer.MAX_VALUE;
         } else {
             return (int)ret;
         }
    }
}
View Code

 

617. Maximum Average Subarray II

https://www.lintcode.com/problem/maximum-average-subarray-ii/description?_from=ladder&&fromId=4

public class Solution {
    /**
     * @param nums: an array with positive and negative numbers
     * @param k: an integer
     * @return: the maximum average
     */
    public double maxAverage(int[] nums, int k) {
        // write your code here
        if(nums==null || nums.length ==0){
            return 0d;
        }
        
        double end =Double.MIN_VALUE;
        double start = Double.MAX_VALUE;
        for(int num:nums){
            end = Math.max(end,num);
            start = Math.min(start,num);
        }
        
        double diff = 1e-6;
        
        while(start+diff<end){
            double mid = start + (end-start)/2;
            if(hasAverage(nums,k,mid)){
                start = mid;
            }else{
                end = mid;
            }
        }
        
        if(hasAverage(nums,k,end)){
            return end;
        }
        
        return start;
    }
    
    public boolean hasAverage(int[] nums, int k,double aver){
        double preMin =0;
        double preSum =0;
        double sum =0;
        for(int i=0;i<k;i++){
            sum+=nums[i]-aver;
        }
        if(sum>=0){
            return true;
        }
        
        for(int i=k;i<nums.length;i++){
            preSum += nums[i-k]-aver;
            preMin= Math.min(preSum,preMin);
            sum+= nums[i]-aver;
            
            if(sum-preMin>=0){
                return true;
            }
        }
        
        return false;
    }
}
View Code

 

633. Find the Duplicate Number

思路:设定重复的数字为x,那么x的特征是数组中比x小的个数>x, 而对于比x小的数y,应该是比y小的个数<=y

https://www.lintcode.com/problem/find-the-duplicate-number/description?_from=ladder&&fromId=4

public class Solution {
    /**
     * @param nums: an array containing n + 1 integers which is between 1 and n
     * @return: the duplicate one
     */
    public int findDuplicate(int[] nums) {
        // write your code here
        int l = 1;
        int r = nums.length-1;
        
        while(l+1<r){
            int mid = l +(r-l)/2;
            if(count(nums,mid)<=mid){
                l = mid;
            }else{
                r = mid;
            }
        }
        
        if(count(nums,l)>l){return l;}
        return r;
    }
    
    //<=mid的数字个数
    private int count(int[] nums,int mid){
        int cnt =0;
        for(int item:nums){
            if(item<=mid){
                cnt++;
            }
        }
        return cnt;
    }
}
View Code

 

362. Sliding Window Maximum

思路:1.插入时,如果发现尾部<插入值,那么尾部无需保留,poll出去,这样会保留一个递减序列

2.最大值即为头部,没加入一个最大值,如果发现该值坐标为窗口第一个值,即下次滑动将不在窗口中,那么poll掉

3.用双端队列实现

https://www.lintcode.com/problem/sliding-window-maximum/description?_from=ladder&&fromId=4

public class Solution {
    /**
     * @param nums: A list of integers.
     * @param k: An integer
     * @return: The maximum number inside the window at each moving.
     */
    public List<Integer> maxSlidingWindow(int[] nums, int k) {
        // write your code here
        List<Integer> res = new ArrayList<>();
        if(nums==null || nums.length<k){
            return res;
        }
        
        //queue中记录下标
        Deque<Integer> queue = new LinkedList<>();
        
        for(int i=0;i<nums.length;i++){
            while(!queue.isEmpty() && nums[i]>nums[queue.peekLast()]){
                queue.pollLast();
            }
            queue.offer(i);
            
            if(i>=k-1){
                res.add(nums[queue.peekFirst()]);
                if(i-k+1==queue.peekFirst()){
                    queue.pollFirst();
                }
            }
            
        }
        
        return res;
    
    }

}
View Code

 

转载于:https://www.cnblogs.com/lizzyluvcoding/p/10795344.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值