分發餅干——很好的解釋模板

好的,孩子,我們來玩一個“喂餅干”的游戲。

0. 問題的本質是什么?

想象一下,你就是個超棒的家長,手里有幾塊大小不一的餅干,而面前有幾個餓著肚子的小朋友。每個小朋友都有一個最小的“胃口”值,比如有的孩子胃口小,只要一塊尺寸為 1 的餅干就滿足了;有的孩子胃口大,得要一塊尺寸至少為 3 的餅干才行。

你的任務很簡單:用你手里的餅干,盡可能地讓更多的孩子吃飽。但是有個規矩:每個孩子只能分到一塊餅干。

  • 孩子們:他們的“胃口”是一個數字列表 g
  • 餅干們:它們的“尺寸”也是一個數字列表 s
  • 滿足條件:一塊餅干的尺寸 s[j],必須大于或等于一個孩子的胃口 g[i],這個孩子才會被滿足。

你的最終目標是找出你最多能滿足多少個孩子。


1. 為什么“貪心”在這里能成功?

這次,我們不用像之前“背包問題”那么復雜的動態規劃了。因為這個“喂餅干”的問題有一個很好的性質,我們可以用一個更簡單的策略來解決,這個策略叫做貪心算法

貪心算法的思路是:

每一步都做出當前看來最好的選擇,希望這些局部的最佳選擇能夠導致最終的全局最佳結果。

那么,這里的“最佳選擇”是什么呢?

有兩種直覺:

  1. 從大到小喂:用最大的餅干去喂胃口最大的孩子。
  2. 從小到大喂:用最小的餅干去喂胃口最小的孩子。

我們來分析一下,為什么“從小到大喂”是一個更好的策略。

假設你有一塊尺寸為 5 的大餅干和一塊尺寸為 1 的小餅干。你面前有兩個孩子,一個胃口為 4,一個胃口為 1。

  • 如果你用大餅干(5)去喂大胃口的孩子(4)

    • 這個孩子滿足了,你還剩下小餅干(1)和另一個小胃口的孩子(1)。
    • 你用剩下的餅干去喂剩下的孩子,這個孩子也滿足了。
    • 結果:兩個孩子都滿足了。
  • 如果你用小餅干(1)去喂小胃口的孩子(1)

    • 這個孩子滿足了,你還剩下大餅干(5)和另一個大胃口的孩子(4)。
    • 你用剩下的餅干去喂剩下的孩子,這個孩子也滿足了。
    • 結果:兩個孩子都滿足了。

從這個例子看,兩種方法都行。但是,再看一個情況:

假設你有一塊尺寸為 5 的大餅干和一塊尺寸為 2 的小餅干。你面前有兩個孩子,一個胃口為 4,一個胃口為 2。

  • 如果你用大餅干(5)去喂大胃口的孩子(4)

    • 這個孩子滿足了,你剩下小餅干(2)和另一個小胃口的孩子(2)。
    • 你用剩下的餅干去喂剩下的孩子,這個孩子也滿足了。
    • 結果:兩個孩子都滿足了。
  • 如果你用小餅干(2)去喂小胃口的孩子(2)

    • 這個孩子滿足了,你剩下大餅干(5)和另一個大胃口的孩子(4)。
    • 你用剩下的餅干去喂剩下的孩子,這個孩子也滿足了。
    • 結果:兩個孩子都滿足了。

看起來好像都一樣。那我們換個角度想:

  • 如果我有一塊尺寸為 2 的小餅干,它能喂飽胃口為 2 的孩子,但喂不飽胃口為 4 的孩子。
  • 如果我有一塊尺寸為 5 的大餅干,它既能喂飽胃口為 2 的孩子,也能喂飽胃口為 4 的孩子。

你覺得,那塊尺寸為 5 的大餅干是不是很寶貴?它能喂飽那些挑剔的大胃口孩子,而小餅干不行。如果我一開始就把大餅干浪費在小胃口孩子身上,那么后面大胃口的孩子就可能餓著了。

所以,最好的策略是:

用最小的餅干,去滿足胃口最小的孩子。

這樣,我們就能把大餅干省下來,留給那些胃口更大的孩子。這個策略就是“貪心”的精髓。


2. 算法步驟和推演過程

根據上面的“貪心”策略,我們來一步步解決這個問題。

**第一步:**把孩子們按胃口從小到大排隊,把餅干們按尺寸從小到大排隊。

  • g = [1, 2, 3] -> 排序后 g = [1, 2, 3]
  • s = [1, 1] -> 排序后 s = [1, 1]

**第二步:**從小到大,一個一個地嘗試用餅干去滿足孩子。

我們用兩個指針,一個指向最小胃口的孩子(child_index),一個指向最小尺寸的餅干(cookie_index)。

  • child_index = 0 (指向胃口為 1 的孩子)
  • cookie_index = 0 (指向尺寸為 1 的餅干)
  • 滿足的孩子數量 satisfied_count = 0

開始匹配:

  1. 孩子 g[0] 的胃口是 1,餅干 s[0] 的尺寸是 1。

    • s[0] (1) >= g[0] (1)?是的,滿足!
    • 我們將這塊餅干給這個孩子。
    • satisfied_count 增加到 1。
    • 孩子和餅干的指針都往前走一步:
      • child_index = 1 (指向胃口為 2 的孩子)
      • cookie_index = 1 (指向尺寸為 1 的餅干)
  2. 孩子 g[1] 的胃口是 2,餅干 s[1] 的尺寸是 1。

    • s[1] (1) >= g[1] (2)?不是,不滿足。
    • 這塊餅干太小了,喂不飽這個孩子。
    • 怎么辦?我們不能把這塊小餅干留給這個孩子,因為他吃不飽。但是這塊餅干也喂不飽后面的任何一個孩子(因為后面的孩子胃口只會更大)。所以,這塊餅干只能扔掉。
    • 我們只讓餅干的指針往前走一步:
      • child_index 保持不變 (指向胃口為 2 的孩子)
      • cookie_index = 2 (沒有更多餅干了)
  3. 餅干用完了!

    • cookie_index 已經超出餅干列表的范圍了。游戲結束。

最終結果:

我們成功滿足了 1 個孩子。

再來一個例子:

  • g = [1, 2], s = [1, 2, 3]
  • 排序后:g = [1, 2], s = [1, 2, 3]
  • child_index = 0, cookie_index = 0, satisfied_count = 0

開始匹配:

  1. 孩子 g[0] (1),餅干 s[0] (1)。

    • s[0] (1) >= g[0] (1)?是的,滿足!
    • satisfied_count = 1。
    • child_index = 1, cookie_index = 1。
  2. 孩子 g[1] (2),餅干 s[1] (2)。

    • s[1] (2) >= g[1] (2)?是的,滿足!
    • satisfied_count = 2。
    • child_index = 2, cookie_index = 2。
  3. 孩子用完了!

    • child_index 已經超出孩子列表的范圍了。游戲結束。

最終結果:

我們成功滿足了 2 個孩子。

這個策略之所以有效,是因為它總是用“勉強夠用”的最小餅干去滿足胃口最小的孩子,從而把更有潛力的餅干留給后續的孩子。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97854.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97854.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97854.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

場景題:如果一個大型項目,某一個時間所有的CPU的已經被占用了,導致服務不可用,我們開發人員應該如何使服務器盡快恢復正常

問:如果一個大型項目,某一個時間所有的CPU的 已經被占用了,導致服務不可用,我們開發人員 應該如何使服務器盡快恢復正常答:應對CPU 100%導致服務不可用的緊急恢復流程面試官,如果遇到這種情況,我會立即按照…

Docker 安裝 RAGFlow保姆教程

前提條件 Ubuntu 服務器(20.04 或 22.04 LTS 推薦) 已安裝 Docker 和 Docker Compose 如果尚未安裝,請先運行以下命令:# 安裝 Docker curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh # 將當前用戶加入 docker 組,避免每次都要 sudo sudo user…

為什么實際工程里 C++ 部署深度學習模型更常見?為什么大家更愛用 TensorRT?

很多人剛接觸深度學習模型部署的時候,都會習慣用 Python,因為訓練的時候就是 PyTorch、TensorFlow 啊,寫起來方便。但一到 實際工程,特別是工業設備、醫療影像、上位機系統這種場景,你會發現大多數人都轉向了 C 部署。…

深入理解 Java 集合框架:底層原理與實戰應用

在日常開發中,集合是 Java 中使用頻率最高的工具之一。從最常見的 ArrayList、HashMap 到更復雜的并發集合,幾乎每一個 Java 程序員都離不開集合框架。集合框架不僅提供了豐富的數據結構實現,還封裝了底層復雜的邏輯,讓開發者能夠…

爬取m3u8視頻完整教程

爬取步驟:1.先找到網頁源代碼2.從網頁源代碼中拿到m3u83.下載m3u84.讀取m3u8文件,下載視頻5.合并視頻首先我們來爬取一個星辰影院的電影:下面我以這個為例:我們需要在源代碼中找到m3u8這個url:緊接著我們利用下面的方法…

Python爬蟲實戰: 基于Scrapy的Amazon跨境電商選品數據爬蟲方案

概述與設計思路 利用Python的Scrapy框架進行大規模頁面抓取和結構化數據提取,配合aiohttp實現高并發請求,從而高效獲取Amazon平臺上的商品列表、詳情、評論等公開信息。通過對這些數據進行清洗與分析,可以識別出有潛力的商品,評估市場競爭程度,并跟蹤競爭對手的動態,為跨…

穩定版IM即時通訊 仿默往APP即時通訊im源碼聊天社交源碼支持二開原生開發獨立部署 含搭建教程

內容目錄一、詳細介紹二、效果展示1.部分代碼2.效果圖展示三、學習資料下載一、詳細介紹 技術開發語言: 后臺管理端:Java GO Mysql數據庫 安卓端:Java iOS端:ob PC端:c 功能簡單介紹: 單聊&#xff…

封裝一個redis獲取并解析數據的工具類

redis獲取并解析數據工具類實現代碼使用示例實現代碼 import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import lom…

23種設計模式——策略模式 (Strategy Pattern)?詳解

?作者簡介:大家好,我是 Meteors., 向往著更加簡潔高效的代碼寫法與編程方式,持續分享Java技術內容。 🍎個人主頁:Meteors.的博客 💞當前專欄:設計模式 ?特色專欄:知識分享 &#x…

CI(持續集成)、CD(持續交付/部署)、CT(持續測試)、CICD、CICT

目錄 **CI、CD、CT 詳解與關系** **1. CI(Continuous Integration,持續集成)** **2. CD(Continuous Delivery/Deployment,持續交付/部署)** **持續交付(Continuous Delivery)** **持續部署(Continuous Deployment)** **3. CT(Continuous Testing,持續測試)** **4.…

【音視頻】WebRTC ICE 模塊深度剖析

原文鏈接: https://mp.weixin.qq.com/s?__bizMzIzMjY3MjYyOA&mid2247498075&idx2&sn6021a2f60b1e7c71ce4d7af6df0b9b89&chksme893e540dfe46c56323322e780d41aec1f851925cfce8b76b3f4d5cfddaa9c7cbb03a7ae4c25&scene178&cur_album_id314699…

linux0.12 head.s代碼解析

重新設置IDT和GDT,為256個中斷門設置默認的中斷處理函數檢查A20地址線是否啟用設置數學協處理器將main函數相關的參數壓棧設置分頁機制,將頁表映射到0~16MB的物理內存上返回main函數執行 源碼詳細注釋如下: /** linux/boot/head.s** (C) 1991 Linus T…

Maven動態控制版本號秘籍:高效發包部署,版本管理不再頭疼!

作者:唐叔在學習 專欄:唐叔的Java實踐 關鍵詞:Maven版本控制、versions插件、動態版本號、持續集成、自動化部署、Java項目管理 摘要:本文介紹如何使用Maven Versions插件動態控制項目版本號和依賴組件版本號,實現無需…

簡述:普瑞時空數據建庫軟件(國土變更建庫)之一(變更預檢查部分規則)

簡述:普瑞時空數據建庫軟件(國土變更建庫)之一(變更預檢查部分規則) 主要包括三種類型:常規檢查、行政區范圍檢查、20X異常滅失檢查 本blog地址:https://blog.csdn.net/hsg77

shell中命令小工具:cut、sort、uniq,tr的使用方式

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 文章目錄前言一、cut —— 按列或字符截取1. 常用選項2. 示例二、sort —— 排序(默認按行首字符升序)1. 常用選項常用 sort 命令選項三、uniq —— 去…

【Linux】Linux開發必備:Git版本控制與GDB調試全指南

前言:在Linux開發流程中,版本控制與程序調試是保障項目穩定性和開發效率的兩大核心環節。Git作為當前最主流的分布式版本控制系統,能高效管理代碼迭代、追蹤修改記錄并支持多人協同開發;GDB(GNU調試器)是Li…

實現 TypeScript 內置工具類型(源碼解析與實現)

目標讀者:已經熟悉 TypeScript 基礎語法、泛型、條件類型的同學。本文按常見工具類型的分類與順序實現并解釋 Partial、Required、Readonly、Pick、Omit、Record、Exclude、Extract、NonNullable、ReturnType、Parameters、ConstructorParameters、InstanceType、Th…

Spring Boot + Nacos 配置中心示例工程

1?? 工程結構 nacos-demo├── pom.xml└── src├── main│ ├── java│ │ └── com.example.nacosdemo│ │ ├── NacosDemoApplication.java│ │ ├── config│ │ │ └── AppProperties.java│ │ └── cont…

(二)文件管理-基礎命令-pwd命令的使用

文章目錄1. 命令格式2. 基本用法3. 高級用法4. 注意事項1. 命令格式 pwd [OPTION]...[OPTION]: 可選選項,用于改變命令的默認行為。最主要的兩個選項是 -L 和 -P。它不需要任何參數(如文件名或目錄名) 2. 基本用法 用法:pwd 是…

Leetcode_202.快樂數_三種方法解決(普通方法解決,哈希表解決,循環鏈表的性質解決_快慢指針)

目錄第一種方法:暴力解法暴力ac代碼:第二種方法:哈希表哈希表ac代碼:第三種方法:根據循環鏈表的性質(快慢指針)第一種方法:暴力解法 最暴力的思路就是直接使用循環往下一直計算,這樣特別浪費時間&#xff…