leetcode - 貪心算法(一)

先導:

  • 爲什麼要做leetcode?
  1. 現實收益角度看,無論你是算法、數據、前端、後端工程師等等,目前大廠互聯網公司面試肯定要考察的,國外google和facebook等等更盛 。都是從leetcode或者類似的網站上出題,如果不熟練,一面都過不了,與心儀的公司失之交臂。

  2. 我認爲它的價值在哪呢?做題本身就可以鍛鍊解決問題的思維能力、邏輯能力。leetcode題目雖然是小問題,正是這種小問題讓你把精力集中在問題本身,而不是去理解繁瑣的處理或者業務邏輯(你不關心的邏輯),是希望找到時間複雜度足夠低的解決方法,一種‘快’感,最大化發揮計算機資源,你會漸漸形成這種意識,慢慢的可以提升對代碼性能的理解。

當然提升代碼性能是重要的,可能提高用戶友好帶來的收益更好,或者代碼簡潔健壯、可維護、安全都非常重要,只是我認爲提升算法性能是最純粹的。

  • 關於語言:

重點要關注的肯定是思路方法,語言沒那麼重要,不過通常來說類似c語言比較底層,細節都要從頭實現,類似python就會有很多現成的模塊可以調用,好模塊開發出來就是給你用的,方便又好用,只是用爽的同時可以深入理解或者實現下就更好了。我是選擇python,應該是比較好看懂的,可以看懂思路後,用自己熟悉的語言實現一下。

另外囉嗦下:

無論你是算法工程師、數據挖掘工程師、自然語言處理工程師還是推薦工程師等等,首先你得是工程師,我們不談需要多豐富的工程能力,什麼高併發多協程各種框架工具分佈式,最基礎的就是必須有紮實的編程功底。機器學習算法工程師在工程實踐中真正花在研究實現算法的時間少之又少,面向應用來說,這就是一個工程問題,工程問題上的改進帶來的收益可能更大,當然去理解業務往往帶來的效果很顯著。總結來說,想要解決好問題,很需要工程能力,過硬的功底是基礎。

做leetcode題,一定要有 章法可循,否則看着題目也無從下手。根據開源大佬的總結,我合併後如下圖,按順序 逐類擊破leetcode題,敬請期待,喜歡就關注下。話不多說,開始分享。

在這裏插入圖片描述

第一篇:貪心算法

貪心策略:保證每次操作都是局部最優的,從而使最後得到的結果是全局最優的。算是一種比較容易想到比較直觀的方法吧。

455. 分發餅乾 (easy)

題目理解:

有一羣孩子和一堆餅乾,每個孩子有一個飢餓度,每個餅乾都有一個大小。每個孩子只能喫最多一個餅乾,且只有餅乾的大小大於孩子的飢餓度時,這個孩子才能喫飽。求解最多有多少孩子可以喫飽。

示例:

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

輸出: 1

解釋:

你有三個孩子和兩塊小餅乾,3個孩子的胃口值分別是:1,2,3。

雖然你有兩塊小餅乾,由於他們的尺寸都是1,你只能讓胃口值是1的孩子滿足。

所以你應該輸出1。

解題思路:

  1. 因爲飢餓度最小的孩子最容易滿足,所以先滿足最小飢餓度的。

  2. 爲了儘量能滿足後面飢餓度高的孩子,給予滿足孩子的所有餅乾中最小的餅乾。

這就是貪心策略,也就是說給予目前飢餓度最小的孩子能喫飽的最小餅乾。

比較方便的實現是,把孩子和餅乾按飢餓度和大小排序,初始化第一個孩子和第一塊餅乾爲起始點(指針),如果孩子飢餓度小於等於餅乾大小,指向孩子和餅乾的點(指針)都往後移動,也就是滿足了這個孩子;否則餅乾丟棄,指向餅乾的點(指針)往後移,再繼續比較和循環下去。

python代碼:

class Solution:
    def findContentChildren(self, g, s):
        g.sort()
        s.sort()
        child = 0
        cookies = 0
        while child < len(g) and cookies < len(s):
            if g[child] <= s[cookies]:
                child += 1
            cookies += 1
        return child

另一種實現:
還有種思路是每次取出最小值,可以構造兩個小頂堆(至於堆是什麼,不瞭解的可以深入去找下理解下,簡單來說就是一種特殊的完全二叉樹,每個結點的值都小於等於左右孩子,建堆的時間複雜度O(n),常用找n個數中最大(小)的k個數時間複雜度O(nlogk),python有現成的模塊heapq),每次拿出飢餓度最小的孩子和最小的餅乾,如果滿足繼續從兩個堆裏都拿出,否則丟棄餅乾,拿出再大一點的餅乾,直到一方拿完。

python代碼:
import heapq

class Solution:
    def findContentChildren(self, g, s):
        heapq.heapify(g)
        heapq.heapify(s)

        child = 0
        while g and s:
            if g[0] <= s[0]:
                heapq.heappop(g)
                heapq.heappop(s)
                child += 1
            else:
                heapq.heappop(s)
        return child

135. 分發糖果 (hard)

題目:
老師想給孩子們分發糖果,有 N 個孩子站成了一條直線,老師會根據每個孩子的表現,預先給他們評分。你需要按照以下要求,幫助老師給這些孩子分發糖果:

  1. 每個孩子至少分配到 1 個糖果。
  2. 相鄰的孩子中,評分高的孩子必須獲得更多的糖果。
    那麼這樣下來,老師至少需要準備多少顆糖果呢?

示例:
輸入: [1,0,2]
輸出: 5
解釋: 你可以分別給這三個孩子分發 2、1、2 顆糖果。

解題思路:

貪心思想,初始化每個人分配1顆糖果,從左到右遍歷,如果左邊孩子評分小於右邊孩子,右邊孩子糖果加1,遍歷完成後換方向從右向左遍歷,如果右邊孩子評分小於左邊孩子,並且左邊孩子的糖果不大於右邊孩子的話,左邊糖果加1,這樣就滿足要求了,是不是很簡單,時間複雜度是O(n)

python代碼:

class Solution:
    def candy(self, ratings):
        ratings_size = len(ratings)
        if ratings_size < 2:
            return ratings_size

        candy = [1] * ratings_size
        for i in range(ratings_size - 1):
            if ratings[i] < ratings[i + 1]:
                candy[i + 1] = candy[i] + 1

        for i in range(ratings_size - 2, -1, -1):
            if ratings[i] > ratings[i + 1]:
                candy[i] = max(candy[i], candy[i+1] + 1)

        return sum(candy)

還有後續,敬請期待!

在這裏插入圖片描述

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