zoukankan      html  css  js  c++  java
  • Wood Cut

    二分查找的一个经典例子

    非递减数列的二分查找

    class Solution {
        /**
         * @param nums: The integer array.
         * @param target: Target to find.
         * @return: The first position of target. Position starts from 0.
         */
        public int binarySearch(int[] nums, int target) {
            //write your code here
            int start=0;
            int end=nums.length-1;
            while(start<=end){
                int mid=(start+end)/2;
                                   
                if(nums[mid]>=target){
                    end=mid-1;
                }else{
                    start=mid+1;
                }
            }
            if(nums[end+1]==target){
                return end+1;
            }
            return -1;
        }
    }

    这个题,看起来很简单,可是仔细一看是含有重复值的非递减数组,那这个时候碰到target这个数字的时候就不能立刻返回了,那么这个时候需要继续在左半部分找更早出现的target。这个时候让end=mid-1, 并且把终止条件变成start<=end,这样如果target就一个,并且因为为了找更靠前的而错过了,那么最后的end+1就是target的位置,因为找到target之后end会后移,那么最后target要么出现在end+1,要么不存在。

     Wood Cut

    Given n pieces of wood with length L[i] (integer array). Cut them into small pieces to guarantee you could have equal or more than k pieces with the same length. What is the longest length you can get from the n pieces of wood? Given L & k, return the maximum length of the small pieces.

     
    Example

    For L=[232, 124, 456]k=7, return 114.

    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
            int maxlen=0;
            for(int i=0;i<L.length;i++){
                if(L[i]>maxlen){
                    maxlen=L[i];
                }
            }
            int start=1;
            int end=maxlen;
            while(start<=end){
                int mid=start+(end-start)/2;
                if(howmuch(L,mid)<k){
                    end=mid-1;
                }else{
                    start=mid+1;
            }
        }
        return start-1;
    
    
    }
        public int howmuch(int[] l,int n){
            int count=0;
            for(int i=0;i<l.length;i++){
                count+=l[i]/n;
            }
            return count;
        }
    }

    解析:

    和二分查找的比较

    这个题很好
    1.如果不仔细想,真想不到二分。其实二分法就是简单暴力遍历的一个折中版本,但是性能好很多。
    2.之前看到别人说,在求(n+m)/2时,应该用n+(m-n)/2,可是一直没有遇到这种情况,今天终于遇到了。。
    3.还要多注意是不是数值越界,或者什么时候要用long型

    本题和非递减数列的二分查找类似
    二分查找中,是找到满足条件的之后再继续找前半部分,因为要找更靠前的。
    这个题,是找到一个木棒的长度可以满足可以截出至少k个木棒的情况之后,不能停,继续找后半部分,因为要找更长的长度。

    如果是需要找一个尽量靠前的target的话,那么这个时候应该是在>=的情况下都要end=mid-1; 最后return end+1
    如果是需要找尽可能靠后的target的话,那么这个时候应该是在<=的情况下都要start=mid+1;最后return start-1

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    2.5.3 表单过滤器
    2.5.2 子过滤器
    2.5.1 位置过滤器:
    2.4 通过属性来选择元素
    2.3 根据层级查找元素
    2.2.4 元素选择器
    2.2.3 Class选择器
    2.2.2 ID选择器
  • 原文地址:https://www.cnblogs.com/tobemaster/p/6014589.html
Copyright © 2011-2022 走看看