89 次榮登活躍榜,最高排名第 9 ,從零學算法第二週週報發佈

第一週週報完整 pdf 版下載地址:

https://t.zsxq.com/rBMVzbM

第二週週報完整 pdf 版星球內下載

作者:算法刷題日記全體星友

版權歸屬:算法刷題日記全體星友

整理:振哥

週報目錄大綱

  • 週報目錄大綱

  • 第二週星球官方數據

  • Day 10:哈希表設計的藝術

    • 1 什麼是哈希表?

    • 2 哈希表原理

    • 3 哈希集

    • 4 哈希映射

    • 5 設計鍵

  • Day 11:寶石和石頭

    • 1 精選答案

    • 2 第一種設計鍵的方法

    • 3 第二種設計鍵的方法

    • 4 第三種設計鍵的方法

    • 今日作業題

  • Day 12:學習鏈表

    • 1 作業總結

    • 2 方法 1 暴力破解:

    • 3 方法 2 哈希表

    • 4 今日作業題

  • Day 13 訪問鏈表第 i 個節點

    • 刪除鏈表的節點

    • 今日作業題

  • Day 14 反轉單鏈表

    • 反轉單鏈表

    • 今日作業題

  • Day 15 程序員爲什麼學算法

    • 昨日作業題總結

    • 迭代法:

    • 今日作業題

  • Day 16 時間複雜度入門

    • 爲什麼要學算法,25位星友給出各自的答案

    • 今日作業題

  • Day17 算法好壞度量:大 O 記號

    • 1 數學定義

    • 2 大 O 記號

    • 3 基本原則

    • 4 今日作業題

第二週星球官方數據

官方推送的星球週報數據顯示:我們的星球上週 89 次榮登星球活躍榜,最高排名第 9 名。

能從 2000 萬用戶數的知識星球中競爭取得這樣的名次,說明我們的星球活躍度很高,感謝大家的參與。

打造一個高質量的學習社區,從零入門算法,方向不變,堅持不變,夢想不變!

Day 10:哈希表設計的藝術

1 什麼是哈希表?

哈希表是一種使用哈希函數組織數據,以支持快速插入搜索的數據結構。

有兩種不同類型的哈希表:哈希集合哈希映射

哈希集合是集合數據結構的實現之一,用於存儲非重複值

哈希映射是映射數據結構的實現之一,用於存儲(key, value)鍵值對

2 哈希表原理

哈希表的關鍵思想是使用哈希函數將鍵映射到存儲桶。

當插入一個新鍵時,哈希函數決定該鍵應該分配到哪個桶中,並將該鍵存儲在相應的桶中;

當搜索一個鍵時,哈希表使用相同的哈希函數來查找對應的桶,並只在特定的桶中進行搜索。

3 哈希集

哈希集是集合的實現之一,對應 Python 中的 set 類型

4 哈希映射

哈希映射是用於存儲 (key, value) 鍵值對的一種實現,對應 Python 中的dict類型

5 設計鍵

設計哈希表時,選擇合適的鍵是一門藝術。

這次 Day 10:字母異位詞分組 打卡題來訓練一下,如何爲哈希表設計合適的鍵。

給定一個字符串數組,將字母異位詞組合在一起。字母異位詞指字母相同,但排列不同的字符串。

示例:

輸入: ["eat", "tea", "tan", "ate", "nat", "bat"]

輸出: [ ["ate","eat","tea"], ["nat","tan"], ["bat"] ] 說明:

所有輸入均爲小寫字母。

不考慮答案輸出的順序。

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:

Day 11:寶石和石頭

1 精選答案

今天很多星友都提交了很不錯的答案,切實感受到設計哈希表的鍵是一門藝術,同時也真正體會到衆人拾柴火焰高,越來越喜歡咱們的星友們和這個平臺,我們一起加油走下去,3個月後遇見更好的自己。

參考大家的打卡,精選幾種解法:

2 第一種設計鍵的方法

對原數組中的每個字符串進行排序,如果是字母異位詞,那排序後的字符串肯定就是相等的。因此可以以排序後的字符串爲Key,Value則爲字符串列表。

3 第二種設計鍵的方法

以元組統計字符串中每個字符出現的次數,並做爲哈希表的Key,Value爲字符串列表

4 第三種設計鍵的方法

質數方式表示,26個小寫字母,以26個質數表示,然後把字符串各個字母相乘即對應的各個質數相乘,得出的結果作爲Key,Value爲字符串列表。

@Leven 星友非常貼心的提示:注意這裏如果字符串長度很長,質數相乘的結果可能會造成int溢出,不過Python3只有長整型,以int表示,基本不會溢出。

怎麼樣,相比大家也切切實實感受到鍵設計的藝術了吧。

今日作業題

給定字符串J 代表石頭中寶石的類型,和字符串 S代表你擁有的石頭。S 中每個字符代表了一種你擁有的石頭的類型,你想知道你擁有的石頭中有多少是寶石。

J 中的字母不重複,J 和 S中的所有字符都是字母。字母區分大小寫,因此"a"和"A"是不同類型的石頭。

示例 1:

輸入: J = "aA", S = "aAAbbbb"  輸出: 3

示例 2:

輸入: J = "z", S = "ZZ"  輸出: 0

注意: S 和 J 最多含有50個字母。

J 中的字符不重複。

class Solution:
    def numJewelsInStones(self, J: str, S: str) -> int:

Day 12:學習鏈表

1 作業總結

石頭與寶石,錯過的星友查看作業題目:https://t.zsxq.com/F6eMfIE

我看星友們提交的答案都很不錯,主要有兩種:

2 方法 1 暴力破解:

時間複雜度是 len(S) * len(J)

@Leven 還給出一種更加 Pythonic 的寫法,利用 sum生成器的方法,好處節省內存,大家不妨留意下。

3 方法 2 哈希表

此解法的時間複雜度是 len(S) + len(J)

根據字符哈希爲出現次數,然後挑選出出現在寶石串的字符個數。

相信大家這10天的訓練,對算法形成一個大概的時間複雜度概念、

等講完鏈表後會單獨有一天講時間複雜度分析。

4 今日作業題

學習鏈表

鏈表這個數據結構是絕對的重中之重,它是線性一維結構的代表,插入和刪除具有 O(1)複雜度,也是後面講二叉樹等的基礎。

因此,鏈表務必要掌握。

鏈表又很容易出錯,所以只能掌握它的基本定義後,多做練習鞏固它。

鏈表的基本結構:

鏈表的順序訪問方法:

那麼,Day 12 作業題來了:鏈表中如何刪除一個節點?

比如,插入節點Green

請根據上面的提示,補全下面代碼:

# 單向鏈表的定義
class ListNode:
    def __init__(self, x):
         self.val = x
         self.next = None
class Solution:
    def deleteNode(self, node):
      # 補全代碼
      #
      #

這是leetcode 237 題,寫完後建議去驗證一下,鏈接:

https://leetcode-cn.com/problems/delete-node-in-a-linked-list/

Day 13 訪問鏈表第 i 個節點

刪除鏈表的節點

刪除鏈表的某個節點 target

下面我們看下星友金金金的精彩回答,從鏈表的建立到刪除指定節點,比較全面。

首先建立 1->7->3->6->5->6 的鏈表,注意查看鏈表的迭代過程,對於習慣了 i+=1 迭代的朋友,可能對鏈表的迭代逐漸熟悉起來:tmp=newNode

上面的刪除是根據val判斷刪除的節點,這與 Day12 題目刪除節點 node 略有區別(題目中 target直接就是一個節點指針)

回答這個題目,注意leetcode中237題,是刪除非尾部節點。

class Solution:
    def deleteNode(self, node):
        node.val = node.next.val
        node.next = node.next.next

舉例,刪除節點 5:

第一步:

第二步:

但是,星友們想過沒有,爲什麼要題目要敲掉刪除的是非尾部節點。

這是因爲,如果刪除尾節點,node.next 就不適應上面的操作步驟,必須要找到倒數第二個節點纔可,但是對於單向鏈表只知道當前刪除節點 node,是無法定位到的。所以才需要這個限制條件。

對於初次接觸鏈表的朋友,可能覺得使用起來比較彆扭,可能需要勤加練習纔行和多多理解。

今日作業題

依然考慮到新接觸鏈表的朋友不習慣使用它,本次作業還是強化下鏈表的基本操作。

# 定義單鏈表
class ListNode:
  def __init__(self, x):
    self.val = x
    self.next = None
def getiNode(head,n,i):
  """
  head:鏈表頭結點
  n:鏈表長度
  i: 返回的第 i 個節點 nodei
  """
  # 
  #補全代碼
  #

Day 14 反轉單鏈表

反轉單鏈表

Day12  作業是刪除鏈表中某個節點node,Day13 遍歷獲得鏈表的第i個節點,至此相信大家對鏈表的基本操作已經掌握。

獲得長度爲n 頭節點爲head鏈表的第i個節點,代碼如下:

def getiNode( head, n, i):
        if i < 0 or i > n: # 檢查邊界條件
            raise IndexError 
        cur = head
        for _ in range(i):
            cur = cur.next
        return cur

對於如下鏈表,值爲23的節點爲表頭,它的指針域取值是下一個節點的指針,依次類推,最後串成一條線:

這是鏈表這個數據結構的特點。

這兩天訓練鏈表時,也有一些星友實際上完成了列表轉化爲鏈表的任務,代碼如下所示:

傳入lst轉化鏈表返回cur_Node:

以上代碼實現有一個巧妙之處:self.head=ListNode(None),設置一個空的哨兵表頭,並使tmpcur_Node分別指向這個空表頭,for 中依次創建一個節點,tmp完成鏈表串聯任務。

遍歷完成後,cur_Node.next 便是真正的鏈表表頭。

初次接觸鏈表的星友,不妨多理解一下,慢慢就會習慣鏈表這種數據結構。

今日作業題

反轉單鏈表檢驗我們是否能夠真正靈活使用它,也是面試頻頻被問道的一個題目。

例如反轉上面單鏈表的方法之一:

黑色結點的下一個結點現在是空。因此,我們停止這一過程並返回新的頭結點 15。

根據以上提示,請補全下面代碼:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
      #
      #補全代碼
      #

寫完後去這裏驗證:

https://leetcode-cn.com/explore/learn/card/linked-list/195/classic-problems/750/

Day 15 程序員爲什麼學算法

昨日作業題總結

反轉鏈表的方法:迭代和遞歸。

迭代法:

Step 1 先標記下這個節點

Step 2 一個迭代步中,curNode 指向 preNode,便完成當前迭代步的反轉

Step 3 每次迭代,preNode 和 curNode 向前移動 1 步

以上步驟歸結爲如下代碼(代碼來自我的星友 Leven):

2 遞歸法 首先反轉自 head.next 後的鏈表,node 此時指向翻轉後鏈表的頭部;最後將 head.next 節點鏈接到 head 節點,最後的最後將 head 節點的 next 域置爲 None,因爲 head 是終點了。

代碼如下:

3 尾遞歸 還有一位星友誠Slime提供了第二種遞歸思路,gif 演示如下:

請停留一秒

代碼如下:

今日作業題

又是七天一週過去了,Day16 我們思考和討論如下話題:

程序員一定要學算法嗎,說出你爲什麼要學習算法?

可以參考:https://www.zhihu.com/question/290268306

加入星球 加入星球,從零學程序員必備的算法,每天在星球內記錄學習過程並打卡,超讚!

打卡 300 天,退還除平臺收取的其他所有費用。

Day 16 時間複雜度入門

爲什麼要學算法,25位星友給出各自的答案

近來經常有朋友問,程序員需要學算法嗎?爲什麼需要學算法?不會算法也能找個Java開發崗造軟件所以就別浪費時間了。如果真要學,算法感覺很高深,需要數學,可是我數學不好,所以放棄它吧?

面對這些疑問,我昨日在星球裏留作業想聽聽星友們怎麼看,程序員爲什麼要學習算法。來,一起看看他們的回答。

回答17

張=小紅= 7 小時前

【打卡】第十五天。算法對我這個數學專業的學生來說,就是一種解決問題的方法。

方法的重要性在於能夠在時間性或者空間性上面比起常規解法有領先。

作爲學生的話,學習算法更多就是讓我在以後就業先人一步????,畢竟你說你會python,然後你就只會調個庫,算法什麼都不會,那隻能算個業餘愛好者吧。

更多回答,請參考:爲什麼還要學算法?且看這 25 個回答,第 17 個回答一針見血!

今日作業題

我們都知道描述機器學習算法好壞的指標常用什麼ROC,AUC,精確率和召回率等,機器學習算法也是算法,除了這些,描述算法好壞的一個必備基礎指標:時間複雜度,衡量時間複雜度的常見方法:大 O 記號。

今天的作業題: 在大 O 記號下,等於多少?是 O()?還是其他?你是怎麼得出來的?

Day17 算法好壞度量:大 O 記號

一般按照步數嚴格計算得到 爲計算規模,但是 往往比較複雜,比如爲: ,如果每一個算法都這麼去計算衡量效果,這顯然不便於交流,所以 1894 年 Paul Bachmann 提出了大 O 記號。

1 數學定義

,進一步表達爲對於任意 ,當計算規模 足夠大時,都滿足下面式子:

根據如上定義,我們可以看出來,大 O 標記下的 不關心繫數 ,並且 是對 T(n) 的一種放大,由此得到是算法的最壞情況,這也是我們最關心的,一個算法的最壞情況是什麼。

2 大 O 記號

,大 O 記號下等於多少?

根據定義,我們這樣放大

根據定義只要滿足 ,所以 爲 O(,即最壞時間複雜度爲

3 基本原則

參考星友 聶磊 2 小時前 的回答:

Day16(計算時間複雜度)學習時間複雜度的基本原則

  1. 只有常數項,認爲其時間複雜度爲O(1)

  2. 順序結構,時間複雜度按加法進行計算

  3. 循環結構,時間複雜度按乘法進行計算

  4. 分支結構,時間複雜度取最大值

  5. 判斷一個算法的時間複雜度時,只需要關注最高次項,忽略最高次項的係數,且其它次要項和常數項也可以忽略

  6. 一般所分析的算法的時間複雜度都是指最壞時間複雜度

忽略次要項和常數項,以及最高項的係數,得出時間複雜度爲 開根號,即²

4 今日作業題

請列舉時間複雜度分別爲

,

,

,

,

,

的算法

如果你想從零學習算法,不妨加入下面星球,現在是最划算的時候,還提供專門的星友微信交流社羣,每天在星球裏記錄自己的學習過程,學習其他星友的解題分析思路。打卡 300 天退換除平臺收取的其他所有費用。

長按二維碼,加入我的星球

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