【二分值域】Leetcode1760. 袋子里最少數(shù)目的球

1760.png

這題體現(xiàn)了二分的一種典型應(yīng)用: “猜答案”

如果沒做到類似的題,很難第一時(shí)間想到用二分去處理,針對這類問題只有多總結(jié),找到不同題目間共性,把本質(zhì)提取出來,才能在第一時(shí)間條件反射般看出它是二分。

拿這道題來說,抓準(zhǔn)題目中的關(guān)鍵字:【最大值】,【最小】

即使得,滿足要求的答案的最大值最小。首先直觀感受是,這個(gè)最大值太模糊了,根本不知道具體怎么去取這個(gè)最大值,怎么定義什么樣的值才算最大值,怎么樣才能找到那個(gè)盡可能大的值,而且保證最大值之間取最小。

如果看完題目有上面的困惑時(shí),這個(gè)時(shí)候再回看題目的限制條件,這個(gè)限制條件就是我們?nèi)フ夷莻€(gè)所謂的 “最大值” 的唯一途徑。

題目的限制條件是:將其中一個(gè)袋子(數(shù)組中的每個(gè)元素表示一個(gè)袋子)里的球,分到 2 個(gè)袋子中去,并且還加了一個(gè)非常重要的限制:操作次數(shù),即如果操作次數(shù)大于1,我們再分多次
以樣例為例:起初只有一個(gè)袋子,袋子里有9個(gè)球,分的操作次數(shù)為2,假設(shè)我們隨便先分一次:
第一次:9:4 5, 即從一號(hào)袋子中拿出5個(gè)放入另外一個(gè)袋子,此時(shí)我們消耗了 1 個(gè)操作次數(shù)
第二次:這時(shí)我們選擇 二號(hào)袋子(隨意模擬的,只為解讀題意),從二號(hào)袋子中拿3個(gè)球到 3 號(hào)袋子中,
這時(shí)三個(gè)袋子中的球分別為:4 2 3

我們要做的就是在 “隨意” 模擬的過程中,把滿足題目要求的值 “猜” 出來。

如何猜?
猜,也是有策略性的猜,因?yàn)閿?shù)據(jù)范圍比較大,為了加速猜取,我們這里就自然想到了用二分,每次排除一半不可能的值。
處理過程中的細(xì)節(jié)點(diǎn),看代碼注釋

    int[] nums;
    int n;
    public int minimumSize(int[] _nums, int k) {
        nums = _nums;
        n = nums.length;
        int l = 1, r = (int)1e9;
        while(l < r) {
            int mid = l + r >> 1;
        /**
    這里是個(gè)重點(diǎn),體現(xiàn)了 “猜” 字,即我們【假設(shè)】當(dāng)前的 mid 就是最終我們要求的那個(gè)值,
但這個(gè)值具體是不是【最合適】的那個(gè)答案,還不一定,要做進(jìn)一步驗(yàn)證
      **/
            if(check(mid, k)) r = mid;
            else l = mid + 1;
        }
        return l;
    }
    boolean check(int mid ,int k) {
        int cnt = 0;
        for(int x : nums) {
           /**
              假設(shè)我們最終要將每個(gè)袋子中放mid個(gè)求,那么要操作幾次
  比如 x = 9, mid = 3. 即9個(gè)球,最終要保證每個(gè)袋子里【至少】有3個(gè)求,要操作幾次?
  9:3 6 => 6: 3 3       可以看到一共需要兩次操作,因?yàn)?9 % 3 == 0,因此需要 (9 / 3 - 1)次
  如果不能整除,比如 x = 10, mid = 3
   10: 3 7  => 7: 3 4 => 4: 3 1  從模擬過程可以看到至少需要3次,才能盡最大可能保證每個(gè)袋子有3個(gè)球,即 10/3 = 3
   **/
            cnt += x / mid;
            if(x % mid == 0) cnt--;
            //如果cnt 太大,說明操作次數(shù)過多,操作次數(shù)過多說明 mid 太小,要適當(dāng)加大 mid
            if(cnt > k) return false;
        }
        return true;
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容