刻意練習:LeetCode實戰 -- Task27.分發餅乾

背景

本篇圖文是LSGO軟件技術團隊組織的 第二期基礎算法(Leetcode)刻意練習訓練營 的打卡任務。本期訓練營採用分類別練習的模式,即選擇了五個知識點(數組、鏈表、字符串、樹、貪心算法),每個知識點選擇了 三個簡單、兩個中等、一個困難 等級的題目,共計三十道題,利用三十天的時間完成這組刻意練習。

本次任務的知識點:貪心算法

貪心算法(greedy algorithm),又稱貪婪算法,是一種在每一步選擇中都採取在當前狀態下最好或最優(即最有利)的選擇,從而希望導致結果是最好或最優的算法。

貪心算法在有最優子結構的問題中尤爲有效。最優子結構的意思是局部最優解能決定全局最優解。簡單地說,問題能夠分解成子問題來解決,子問題的最優解能遞推到最終問題的最優解。

貪心算法與動態規劃的不同在於它對每個子問題的解決方案都做出選擇,不能回退。動態規劃則會保存以前的運算結果,並根據以前的結果對當前進行選擇,有回退功能。


題目

  • 題號:455
  • 難度:簡單
  • https://leetcode-cn.com/problems/assign-cookies/

假設你是一位很棒的家長,想要給你的孩子們一些小餅乾。但是,每個孩子最多隻能給一塊餅乾。對每個孩子i,都有一個胃口值gi,這是能讓孩子們滿足胃口的餅乾的最小尺寸;並且每塊餅乾j,都有一個尺寸sj。如果sj >= gi,我們可以將這個餅乾j分配給孩子i ,這個孩子會得到滿足。你的目標是儘可能滿足越多數量的孩子,並輸出這個最大數值。

注意:

你可以假設胃口值爲正。

一個小朋友最多隻能擁有一塊餅乾。

示例 1:

輸入: [1,2,3], [1,1]

輸出: 1

解釋: 
你有三個孩子和兩塊小餅乾,3個孩子的胃口值分別是:1,2,3。
雖然你有兩塊小餅乾,由於他們的尺寸都是1,你只能讓胃口值是1的孩子滿足。
所以你應該輸出1

示例 2:

輸入: [1,2], [1,2,3]

輸出: 2

解釋: 
你有兩個孩子和三塊小餅乾,2個孩子的胃口值分別是1,2。
你擁有的餅乾數量和尺寸都足以讓所有孩子滿足。
所以你應該輸出2.

示例 3:

輸入: [10,9,8,7], [5,6,7,8]

輸出: 2

實現

第一種:貪心算法

貪心策略:優先滿足胃口小的小朋友的需求。

  • gs升序排序
  • 初始化兩個索引ij分別指向gs初始位置

g[i] <= s[j]:餅乾滿足胃口,把能滿足的孩子數量加1,並移動指針i++,j++

g[i] > s[j]:無法滿足胃口,j++,繼續查看下一塊餅乾是否可以滿足胃口。

  • 執行結果:通過
  • 執行用時:160 ms, 在所有 C# 提交中擊敗了 58.21% 的用戶
  • 內存消耗:30.6 MB, 在所有 C# 提交中擊敗了 11.11% 的用戶
public class Solution
{
    public int FindContentChildren(int[] g, int[] s)
    {
        Array.Sort(g);
        Array.Sort(s);

        int i = 0;
        int j = 0;            
        int result = 0;

        while (i < g.Length && j < s.Length)
        {
            if (s[j] < g[i])
            {
                j++;
            }
            else
            {
                i++;
                j++;
                result++;
            }
        }
        return result;
    }
}

對以上代碼進行簡化:

  • 執行結果:通過
  • 執行用時:160 ms, 在所有 C# 提交中擊敗了 58.21% 的用戶
  • 內存消耗:30.4 MB, 在所有 C# 提交中擊敗了 11.11% 的用戶
public class Solution
{
    public int FindContentChildren(int[] g, int[] s)
    {
        Array.Sort(g);
        Array.Sort(s);

        int i = 0;
        int j = 0;
        int result = 0;

        while (i < g.Length && j < s.Length)
        {
            if (s[j] >= g[i])
            {
                i++;
                result++;
            }
            j++;
        }
        return result;
    }
}

Python 語言

  • 執行結果:通過
  • 執行用時:336 ms, 在所有 Python3 提交中擊敗了 15.90% 的用戶
  • 內存消耗:15.3 MB, 在所有 Python3 提交中擊敗了 5.49% 的用戶
class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        g = sorted(g)
        s = sorted(s)
        i, j, result = 0, 0, 0
        while i < len(g) and j < len(s):
            if s[j] >= g[i]:
                i += 1
                result += 1
            j += 1
        return result

往期活動

LSGO軟件技術團隊會定期開展提升編程技能的刻意練習活動,希望大家能夠參與進來一起刻意練習,一起學習進步!


我是 終身學習者“老馬”,一個長期踐行“結伴式學習”理念的 中年大叔

我崇尚分享,渴望成長,於2010年創立了“LSGO軟件技術團隊”,並加入了國內著名的開源組織“Datawhale”,也是“Dre@mtech”、“智能機器人研究中心”和“大數據與哲學社會科學實驗室”的一員。

願我們一起學習,一起進步,相互陪伴,共同成長。

後臺回覆「搜搜搜」,隨機獲取電子資源!
歡迎關注,請掃描二維碼:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章