ChatGPT 透過谷歌演算法面試,年薪 18.3 萬美金

彭旭銳發表於2023-04-01

本文已收錄到 AndroidFamily,技術和職場問題,請關注公眾號 [彭旭銳] 提問。

宣告:此圖片由 MidJourney 生成
未經訓練,不屬於任何真實人物

大家好,我是小彭。

2023 開年以來,全球媒體最火爆的熱點莫過於一個生成式 AI 聊天機器人 —— ChatGPT,我們都被大量的資訊刷屏了。在這些資訊中,你或許看過這樣一則新聞 《ChatGPT Passes Google Coding Interview for Level 3 Engineer With $183K Salary》,它說 ChatGPT 透過了谷歌工程師面試,則這個職位的年薪有 18.3 萬美元。

讓會不會讓一些小夥伴產生焦慮的想法?

圖片截圖自新聞:https://www.pcmag.com/news/chatgpt-passes-google-coding-interview-for-level-3-engineer-with-183k-salary

谷歌面試是會考演算法的,ChatGPT 已經具備這麼強的演算法能力了嗎?如果答案是肯定的,那麼我們藉助 ChatGPT 的力量幫助提高演算法能力,是不是可行的想法。

試想一下:我們要學習一個演算法或者新知識新領域,直接將問題拋給 AI,讓 AI 直接傳道授業解惑,直接向你總結出全社會沉澱下來的最有價值的經驗、方法論、內容或觀點,你甚至都不需要去上學、找資料、看書。遇到不理解的地方可以繼續向 AI 追問,AI 還會非常有耐心的幫你解釋……

未來,固然需要想象。

現實,ChatGPT 能做到嗎?

正好,最近有群友讓我寫一篇演算法的入門文章,藉此機會,就讓我們來學習如何使用 ChatGPT 輔助演算法學習:

在接下來的幾篇文章中,小彭將繼續為你介紹 AI 技術的使用攻略以及實踐感悟。

如果你對 ChatGPT 還不夠熟悉,希望我能夠為你提供一些指引。

讓我們開始吧!


今天文章比較長,寫個簡單的大綱:

1、LeetCode 演算法題學習鏈路簡要分析

2、ChatGPT 助手從入門到放棄

2.1 ChatGPT 的能力和限制

2.2 ChatGPT 的使用原則

3、面向 ChatGPT 程式設計的正確開啟方式

4、總結


1. LeetCode 演算法題學習鏈路簡要分析

首先,請你思考:完整地學習一道演算法題包含哪些步驟或動作:

  • 步驟一:複製程式碼 ?
  • 步驟二:貼上執行 ?
  • 步驟三:自我滿足 ?

說笑了,這麼有任何價值(求饒),應該是:

  • 階段 1 - 白板編碼
  • 階段 2 - 閱讀優質題解
  • 階段 3 - 抽象問題模型

1.1 階段 1 - 白板編碼

這裡所說的 “白板” 並不是真的在白板上寫出答案,而是說在無外力輔助的環境下獨立解出題目。這個階段不僅僅是寫程式碼,而是:

  • 1.1 閱讀: 快速閱讀題目資訊,提取出題目的關鍵資訊,包括題目目標、關鍵約束、輸入輸出資料型別、資料量大小等;
  • 1.2 抽象: 結合已掌握的演算法知識抽象出題目的問題模型,並思考解決問題的演算法,需注意演算法複雜度能否滿足問題的資料量上界;
  • 1.3 編碼: 題目一般有多種演算法實現,優先寫出複雜度最優的版本。如果做不到,則先寫出最熟悉的演算法,再最佳化為複雜度更優的演算法(在面試和競賽中策略類似);
  • 1.4 檢查: 檢查題目條件並完善程式碼,包括問題約束、陣列越界、大數越界、小數精度、初始狀態值、目標狀態值等;
  • 1.5 除錯: 重複第 1 - 4 個動作直到題目透過所有測試用例。

至此,你已經 “透過” 這道題(或許沒有),然而你只是對已經學過的知識複習了一遍,對這部分演算法更加熟悉了,但是並沒有知識增量,所以你需要進入階段 2:

1.2 階段 2 - 閱讀優質題解

閱讀優質題解一直是最快的提升演算法能力的途徑,也是整個學習鏈路中最花時間的部分。好在社群中有非常多熱愛演算法的小夥伴,即使是剛剛釋出的周賽題目,也不會出現沒有題解的情況。

推薦一些優質演算法題解作者:

因此,閱讀題解階段主要障礙就是看不懂,哪裡看不懂呢?

  • 難點 1 - 演算法: 理解演算法本身,文字、註釋、程式碼、圖表這些都是演算法的表現形式;
  • 難點 2 - 演算法推導: 理解從題目一步步到演算法的推導過程(有些題解會省略推導過程);
  • 難點 3 - 演算法證明: 理解演算法的嚴格證明過程,特別是貪心演算法(有些題解會省略證明過程)。

舉個例子,題目 743. 網路延遲時間 有「 Dijkstra + 最小堆 」的演算法,那麼:

  • 演算法:理解 “每輪迭代從小頂堆中獲取候選集裡距離起點最短路長度最小的節點,並使用該點鬆弛相鄰邊” 就是理解演算法本身;
  • 演算法推導:理解 “暴力 BFS/DFS → Floyd → 樸素 Dijkstra → Dijkstra + 最小堆” 就是理解演算法推導過程;
  • 演算法證明:理解 “選擇候選集中距離起點最短路長度最小的節點的方案不存在更優解” 就是理解演算法證明過程。

有些題目會由多個解法,等於有多個演算法、多個演算法推導過程以及多個演算法證明過程,那麼你要理解的資訊量是成倍增加的。這裡要根據時間和優先順序有所取捨。

理解了閱讀題解階段的主要障礙,那麼這些障礙是由哪些原因導致的呢?

  • 原因 1:題解結構缺失: 有的題解只提供了可執行的程式碼,但是省略了推導過程和證明過程,甚至沒有複雜度分析(題解:沒有複雜度分析我不完整了);
  • 原因 2 - 思維複雜度過高: 有些題解結果完整,講解也很詳細,但是其中某些難點或某幾行程式碼思維複雜度很高(大腦複雜度 $O(n^n)$);
  • 原因 3 - 前置知識缺失: 有些演算法需要一些前置知識基礎,例如 Dijkstra 演算法就需要有圖論基礎(基礎不牢地動山搖);
  • 原因 4 - 程式碼語言缺失: 有些題解只會提供一種語言的程式碼(說的就是我);

在你閱讀題解時,你還會嘗試根據題解寫出程式碼,相當於回退到階段 1 的編碼階段,但這個階段會盡可能多地藉助外力輔助。 因為此時編碼不是目的,是透過編碼的方式加深對演算法的理解。

至此,你不僅理解了題解的大部分資訊,還手擼了一遍程式碼,恭喜你已經 “學會” 這道題,但是如果換一道變型題呢?這道題學會了,並不代表這一類的題目你都學會了,所以你需要進入階段 3:

1.3 階段 3 - 抽象問題模型

抽象問題模型就是你在階段 1-2 抽象步驟中做的事情。

你之所以能在短時間解決演算法問題, 是因為你曾經做過這道問題,或者曾經做過這類問題,曾經抽象過這類問題(天賦選手除外),這就是我們常說的多做多刷多總結。

所謂抽象,就是總結出題目的模型 / 套路,怎麼做呢?

  • 3.1 題目型別: 例如數學、雙指標、回溯、動態規劃、貪心、資料結構就是一級題目型別。繼續細分下去,雙指標又分為二分查詢、滑動視窗、同向 / 相向雙指標,動態規劃又分為線性 DP、樹形 DP、轉壓 DP、數位 DP 等,回溯又分為排列、組合、子集等等;
  • 3.2 演算法模型: 模型就是我們說的解題模板 / 板子。例如二分查詢有排除嚴格不成立方向的模型,揹包問題有 01 揹包和完全揹包和滾動陣列的模型,線段樹有樸素線段樹 +Lazy 的模型,質數有暴力和篩法的模板等等;
  • 3.3 編碼技巧: 例如負數取模技巧、陣列補 0 位技巧、連結串列 Dummy 節點技巧、除法轉乘法技巧等等;

抽象題目模型需要建立在大量閱讀量和刷題量的基礎上,是最重要的環節。經過後文實驗驗證,目前 GPT-3.5 和 GPT-4 都無法達到頂尖演算法高手的抽象水平。

最後,你還需要將整個思考過程按照題目編號記錄下來,方便未來的你查閱,小彭就是簡單記錄在 Github 上。有時候我重新做一道題後,會發現今天寫的程式碼質量比幾個月前寫的的程式碼質量高出很多,也在見證自己的成長。

至此,學習鏈路分析結束!

1.4 LeetCode 演算法題學習鏈路小結

完成 LeetCode 演算法題學習鏈路的簡要分析後,用一個表格總結:

階段 動作 描述
1、白板編碼 1.1 閱讀 快速閱讀題目資訊,提取出題目的關鍵資訊
1.2 抽象 結合已掌握的演算法知識抽象出題目的問題模型
1.3 編碼 擼程式碼
1.4 檢查 檢查題目條件並完善程式碼
1.5 除錯(for Loop) 重複第 1 - 4 個動作直到題目透過所有測試用例
2、閱讀優質題解 2.1 理解演算法 理解演算法本身,文字、註釋、程式碼、圖表這些都是演算法的表現形式
2.2 理解演算法推導過程 理解從題目一步步到演算法的推導過程
2.3 理解演算法證明過程 理解演算法的嚴格證明過程,特別是貪心演算法
2.4 輔助編碼(Async) 擼程式碼
3、抽象問題模型 3.1 抽象題目型別 例如數學、雙指標、回溯、動態規劃、貪心、資料結構
3.2 抽象演算法模型 例如二分查詢、揹包問題、線段樹 + Lazy、質數
3.3 抽象編碼技巧 例如負數取模技巧、陣列補 0 位技巧、連結串列 Dummy 節點技巧、除法轉乘法

接下來,我們開始思考如何將 ChatGPT 有機地融入到演算法題的學習鏈路中:


2. ChatGPT 助手從入門到放棄

ChatGPT 在對自然語言理解方面的進步是令人驚歎的,很多情況下只需要輸入一個模糊的指令,ChatGPT 就能直接生成比較完整的答案。

然而,隨著問題的深入和複雜化,ChatGPT 的錯誤和問題也逐漸顯露出來,這就是我從入門到 “放棄” 的整個過程:

2.1 向 ChatGPT 提問的一個誤區

如果我們直接把問題交給 ChatGPT,試圖讓它直接輸出詳細的題解,會發生什麼?

可以看到,這份回答有演算法型別、演算法描述、演算法推導過程、演算法實現和複雜度分析,算是一份相對完整的題解,但遠遠還談不上優質,與 LeetCode 上優質的題解比相去甚遠。

不是把 ChatGPT 吹到天上去了嗎,問題出在哪裡呢?

因為我們提出的一個開放(open-ended)問題,而這種提問方式對 ChatGPT 是低效的:

  • 詳細:怎麼定義詳細?100 個字還是 1000 個字叫詳細?
  • 優質:怎麼定義優質?需要多少種演算法,需要舉一反三嗎?
  • 題解:怎麼定義題解?需要包含哪些資訊?

總之,“請你寫出詳細優質的題解”、“你能幫我做這道題嗎” 和 “請你告訴我這道題” 這三種問法,在 ChatGPT 看來並沒有本質區別,而且實測結果出奇地一致(請避免 ?)。

2.2 一個萬能的 ChatGPT prompt 模板

在經過一整天被人工智障折磨,以及閱讀 《The Art of ChatGPT Prompting》後,我總結出一個提問模板:

  • 1、角色:限定知識領域(注意:New Bing 玩角色扮演出錯機率偏高);
  • 2、目標:一句話概括需要的幫助;
  • 3、要求:對目標補充的具體清晰的要求,儘量表達清晰,避免模糊,一般採用 Do 和 Do not 格式;
  • 4、舉例(可選):輸入輸出樣例。

後來我發現 OpenAI 在 GPT-4 的測試論文 《Sparks of Artificial General Intelligence: Early experiments with GPT-4》中,也採用了類似 “角色-目標 - 要求 - 舉例” 的模板 ☺。

GPT-4 早期測試報告:https://arxiv.org/pdf/2303.12712.pdf

2.3 一個被逼瘋的 prompt

經過和 ChatGPT 的來回拉扯後,我終於寫出一版相對滿意的 prompt。我試圖讓 ChatGPT 寫出優質的題解,類似於要求 ChatGPT 寫一篇文章。

我需要你擔任演算法教師和指導者,你需要給出一道 LeetCode 問題的程式碼和解題思路。
要求:
1、使用中文回答,使用 Kotlin 語言
2、程式碼必須帶有註釋
3、確保每個解法是嚴格不同的演算法,並且每個解法包含演算法名稱、演算法概括,演算法詳細描述、演算法推導過程、程式碼實現、複雜度分析
4、先總結題目的解法個數,以及每個演算法的演算法名稱
5、先輸出複雜度最差的暴力解法,再依次輸出複雜度更優的解法
6、不要輸出題目描述和測試用例
題目:
718. 最長重複子陣列

這道題有 4 種解法:

  • 1、使用暴力解法,列舉所有子陣列,判斷是否為重複子陣列。
  • 2、使用動態規劃解法,以二維陣列 dp[i][j] 記錄以A[i] 和 B[j] 為結尾的最長重複子陣列長度。
  • 3、使用滑動視窗解法,列舉 A 和 B 所有的對齊方式,計算每種對齊方式的最長重複子陣列長度。
  • 4、使用二分查詢解法,最長重複子陣列長度存在單調性,使用二分查詢檢查是否存在長度為 len 的重複子陣列。

那 ChatGPT 會給出令人滿意的答覆嗎?

可以看到:雖然回答比用 “請你寫出詳細優質的題解” 提問得到的回答最佳化了很多,但是連最簡單的程式碼註釋要求都沒有滿足,更不用說和 LeetCode 上的優質題解相比。

何苦看 ChatGPT❓

至於被爆吹的 New Bing 和 GPT-4 模型呢?實驗結果和 GPT-3.5 沒有明顯差別(失望)。

GPT-4 實驗結果:https://poe.com/s/VIkeeiqjDGVfuym0Kn5B

2.4 降低要求

在文章 《The Art of ChatGPT Prompting》中,提到:“It's important to provide the ChatGPT with enough information to understand the context and purpose of the conversation, but too much information can be overwhelming and confusing.”

圖片截圖自原文:https://fka.gumroad.com/l/art-of-chatgpt-prompting

那麼,有沒有可能是因為我們提出的資訊量太大,導致 ChatGPT 無法聚焦呢?

我們嘗試讓 ChatGPT 針對某個演算法輸出題解:

我需要你擔任演算法教師和指導者,你需要給出一道 LeetCode 問題的程式碼和解題思路。
要求:
1、使用中文回答,使用 Kotlin 語言;
2、使用二分查詢+雜湊表的解法
3、包含演算法、演算法概括,演算法詳細描述、演算法推導過程、程式碼實現、複雜度分析
4、不要輸出題目描述和測試用例
題目:
718. 最長重複子陣列

大同小異,這也說明上一節的測試結果並不是因為要求過多導致。

2.5 重新認識 ChatGPT 的能力和限制

在經歷過反覆被折磨後,我決定放棄讓 ChatGPT 寫題解的想法,原因是:

  • 1、ChatGPT 確實有總結提煉的能力,但要 ChatGPT 給出準確、全面、深度的答案,目前 ChatGPT 做不到;
  • 2、相比於總結,人類更看重的是對問題的深度拆解和建構能力,目前 ChatGPT 做不到。

其實,目前爆火的兩類 AI 技術,都是工具型 AI,而不是科幻作品中常見的通用型 AI。無論是基於大語言模型 LLM 的 ChatGPT,還是基於擴散演算法 Diffusion 的 MidJourney 等繪畫工具,本質上都是使用海量資料針對特定場景訓練出的模型。它們擁有讓全人類難望塵莫及的資料處理能力,但它的能力上限也被封印在這個軀殼中。

AI 這個詞,被泛化了。

像 ChatGPT 就是使用網際網路上海量的文字資料作為大型預訓練語料庫,讓機器從語料庫中學習語言模型,並透過 Transformer 模型來預測下一個單詞的機率分佈。這裡面有 2 個關鍵詞:

  • 機率: ChatGPT 語言模型的數學基礎是機率論,透過預測詞的機率來輸出答案,它絕對無法給出 100% 準確的回答,更不用說自主創作,甚至經常一本正經地給出自相矛盾的回答(GPT-4 也一樣)。“原創想法的拙劣表達” 比 “清晰表達的非原創想法” 更有價值,此觀點我們在《什麼是原創?獨立完成就是原創嗎?》這篇文章裡討論過。
  • 語料庫: ChatGPT 是基於網際網路上的公共資料庫(截止至 2021 年),不包含網際網路上的私有資料庫,企業和個人的私有資料庫,超出語料庫範圍的內容它無法給出答案的。

圖片截圖自 InstructGPT 論文 https://arxiv.org/pdf/2203.02155.pdf

回到文章開頭的那個想象,ChatGPT 能做到嗎?—— ChatGPT 不僅做不到,還遠遠做不到,在可見的未來,也不太可能做到。

2.6 在學習過程中使用 ChatGPT 的指導原則

話說回來,我們給 ChatGPT 一個很高的期待值,然後以它達不到期待值為由否定它,是客觀的嗎?不是。

剛開始使用 ChatGPT 的時候,它所表現的能力的確讓我們很多人感覺非常驚歎。只是隨著實踐使用次數增多,隨著提問問題的深入和複雜化,ChatGPT 的錯誤才開始逐漸顯現出來,直到最後令人失望而已,是我們把它捧得太高了!

所以,在使用 ChatGPT 等 AI 技術時,我們應該遵循哪些基本原則呢:

  • 原則 1 - 主動降低預期:

不要神化 ChatGPT,也不要否定 ChatGPT,而是降低對 AI 的預期,主動掌握使用和控制 AI。

我認為將 ChatGPT 稱為人類有史以來最智慧的一本字典,或許是正確的定位。

在搜尋引擎時代,資訊以資料的形式儲存在全世界的資料庫中,我們要從這些資訊中獲得解決方案,就需要花費大量的時間去觸達、篩選、閱讀和加工。而在使用 ChatGPT 後,ChatGPT 能夠幫我們搜尋和整理資訊,並直接呈現出整理後的資訊,即使我們對這個領域一無所知。

ChatGPT 最大的意義,在於它能夠解決 “資訊量太大 ”而 “注意力太少” 的矛盾。它能夠在一瞬間將每個人在木桶效應中最短的那根短板提高到平均水平,每個人的延展性將被極大地延伸。

因此,雖然目前 AI 無法有效解決綜合性的複雜問題,但對於比較基本的模式化的問題,ChatGPT 能在短時間生成完整的方案,也是相當厲害的。把對 ChatGPT 的預期降低,理解它的能力和限制,才能更好的控制它。

  • 原則 2 - 監督和指導:

不要期望 ChatGPT 能夠自主解決問題,更不用擔心 AI 會取代人類。

ChatGPT 的確可以協助我們完成某些特定任務 / 特定動作,但它更需要在人類的監督和指導下才能有效產出,更無法代替人類的創造力和解決問題的思考力。

還有,大家都遇到過 ChatGPT 遇到複雜問題就開始一本正經地胡說八道,此時需要人類去主動查驗和指導它直到給出正確答案。有時候,與其花時間調教 ChatGPT,還不如自己花時間一五一十解決問題來得快。

  • 原則 3 - 思考的權利:

將思考的權利讓渡給 AI,是危險的。

ChatGPT 確實具有總結的能力,但是過渡依賴於 AI 來輔助學習,放棄思考的過程,放棄探索未知的過程,放棄折磨大腦皮層的過程,是危險的。長此以往勢必會造成學習能力和主觀能動性的退化,抗壓能力的退化(窺視真理,得到的就一定是真理嗎)。

很多時候,我們追求的不僅僅是最終的答案,還包括尋求答案的過程,是一種所謂的 “心流” 狀態。因此,越是折磨大腦皮層的動作,我們越不能讓渡給 AI,而那些需要花費大量時間的重複的搜尋整理動作,不交給 AI 還交給誰呢?

階段 結論
1、白板編碼 100% 不暴露給 AI
2、閱讀優質題解 理解過程儘量不暴露給 AI,使用 AI 作為 Checker
3、抽象問題模型 使用 AI 查詢和整理資訊

至此,我們結論確定。

接下來基於此結論開始使用 ChatGPT 輔助學習過程中的單個動作:


3. 面向 ChatGPT 程式設計的正確開啟方式

3.1 使用 ChatGPT 輸出提示

在做題時,有時候一下子卡住了但是又想挑戰自己,可以讓 ChatGPT 輸出提示試試看,類似於 LeetCode 上的 Hint 功能。

我需要您擔任演算法教師和指導者,給出一道 LeetCode 問題的 5 條提示。
要求:
1、用中文回答,回答精簡,限制在 15 字內
2、如果存在多種解法,優先提示覆雜度最差的暴力解法,再依次提示覆雜度更優的解法
問題:718. 最長重複子陣列

這次 AI 給出了 5 個解法,而在之前的回答只給出了 2 個解法。

3.2 使用 ChatGPT 補齊題解結構

有的題解只提供了可執行的程式碼,但是省略了推導過程或證明過程,甚至沒有複雜度分析,我們可以題解交給 ChatGPT 補齊,以 newhar 的這篇題解為例:

我需要你擔任演算法教師和指導者,你需要補齊一道 LeetCode 題的題解。
要求:
1、使用中文回答;
2、為程式碼增加註釋
3、分析時間和空間複雜度
4、解釋這個演算法
程式碼:
class Solution {
public:
    int collectTheCoins(vector<int>& coins, vector<vector<int>>& edges) {
        int n = coins.size();
        unordered_set<int> nes[n];
        for(const auto& e : edges) {
            nes[e[0]].insert(e[1]);
            nes[e[1]].insert(e[0]);
        }
        // 1. 刪除所有的無金幣的葉子節點,直到樹中所有的葉子節點都是有金幣的(類似拓撲排序)
        vector<int> deleted(n, 0);
        queue<int> q;
        for(int i = 0; i < n; ++i) 
            if(nes[i].size() == 1 && coins[i] == 0) 
                q.push(i);
        
        while(q.size()) {
            int cur = q.front(); q.pop();
            deleted[cur] = 1;
            for(int ne : nes[cur]) {
                nes[ne].erase(cur);
                if(coins[ne] == 0 && nes[ne].size() == 1) {
                    q.push(ne);
                }
            }
        }
        
        // 2. 刪除樹中所有葉子節點,及其相鄰邊(刪兩次)
        for(int iter = 0; iter < 2; ++iter) {
            for(int i = 0; i < n; ++i) {
                if(!deleted[i] && nes[i].size() == 1) {
                    deleted[i] = 1;
                }
            }
            for(int i = 0; i < n; ++i) {
                if(deleted[i]) {
                    for(int ne : nes[i]) {
                        nes[ne].erase(i);
                    }
                }
            }
        }
        
        // 3. 答案就是剩下的樹中的邊數
        int res = 0;
        for(const auto& e : edges)
            if(!deleted[e[0]] && !deleted[e[1]]) 
                res += 2;
        
        return res;
    }
};

GPT-4 實驗結果:https://poe.com/s/VIkeeiqjDGVfuym0Kn5B

3.3 使用 ChatGPT 輔助閱讀

有些題解結果完整,講解也很詳細,但是其中某些難點或某幾行程式碼過於複雜,可以針對性提出問題,ChatGPT 也有能力結合上下文回答。

3.3 使用 ChatGPT 翻譯程式碼

有些題解只會提供一種語言或少部分語言的程式碼,比如 我的題解 一般只有 Java / Kotlin 語言,可以讓 ChatGPT 翻譯:

我需要你擔任演算法教師和指導者,你需要將程式碼翻譯為 Python:
要求:
1、包含程式碼註釋
程式碼:
class Solution {
    fun collectTheCoins(coins: IntArray, edges: Array<IntArray>): Int {
        val n = coins.size
        // 入度表
        val inDegrees = IntArray(n)
        // 領接表
        val graph = HashMap<Int, MutableList<Int>>()
        for (edge in edges) {
            graph.getOrPut(edge[0]) { LinkedList<Int>() }.add(edge[1])
            graph.getOrPut(edge[1]) { LinkedList<Int>() }.add(edge[0])
            inDegrees[edge[0]]++
            inDegrees[edge[1]]++
        }
        // 剩餘的邊
        var left_edge = edges.size // n - 1
        // 1、拓撲排序剪枝無金幣子樹
        val queue = LinkedList<Int>()
        for (node in 0 until n) {
            // 題目是無向圖,所以葉子結點的入度也是 1
            if (inDegrees[node] == 1 && coins[node] == 0) {
                queue.offer(node)
            }
        }
        while (!queue.isEmpty()) {
            // 刪除葉子結點
            val node = queue.poll()
            left_edge -= 1
            // 修改相鄰節點
            for (edge in graph[node]!!) {
                if (--inDegrees[edge] == 1 && coins[edge] == 0) queue.offer(edge)
            }
        }
        // 2、拓撲排序剪枝與葉子結點距離不大於 2 的節點(裁剪 2 層)
        // 葉子節點
        for (node in 0 until n) {
            if (inDegrees[node] == 1 && coins[node] == 1) {
                queue.offer(node)
            }
        }
        for (node in queue) {
            // 2.1 刪除葉子結點
            left_edge -= 1
            // 2.2 刪除到葉子結點距離為 1 的節點
            for (edge in graph[node]!!) {
                if (--inDegrees[edge] == 1) left_edge -= 1
            }
        }
        // println(inDegrees.joinToString())
        // coins=[0,0],edges=[[0,1]] 會減去所有節點導致出現負數
        return Math.max(left_edge * 2, 0)
    }
}

ChatGPT 會根據原有程式碼邏輯轉層翻譯為目標語言,基本完成得不錯。美中不足的是,我從來沒遇到過程式碼一次轉換後不出錯的情況,需要反覆指導才能改對,實際作用一般。

3.4 使用 ChatGPT 規範程式碼

我們可以將自己寫的程式碼交給 ChatGPT 做 CodeReview:

我需要你擔任演算法教師和指導者,你需要對程式碼做 CodeReview:
要求:
1、評價程式碼規範性
2、指出不足指出
3、給出改進後的版本
程式碼:略

圖片過大,只擷取部分資訊。

大部分是一本正經地胡說八道,效果非常一般,跟市面上已有的 Review 工具完全比不了,果然 CodeReview 是個經驗活 ?!!

GPT-4 實驗結果:https://poe.com/s/XelhIjmHxWFtbnZpLmEd

3.5 使用 ChatGPT 推薦相似題目

我們可以讓 ChatGPT 舉出相似題型:

我需要你擔任演算法教師和指導者,你需要給出 10 道同型別題目和連結:
題目:
718. 最長重複子陣列

可以看到,ChatGPT 的學習深度只能分析到 “動態規劃” 這一層,推薦的題目實際關聯度不高。

我們嘗試增加限定條件,例如要求演算法模型都包含動態規劃、滑動視窗和二分查詢:

我需要你擔任演算法教師和指導者,你需要給出 10 道同型別題目和連結:
要求:
1、都包含動態規劃、滑動視窗和二分查詢解法
題目:
718. 最長重複子陣列

這次相似度很高,不錯。

是不是逐漸掌握調教 ChatGPT 的正確方式?更多 case 就不再展示了,希望這篇文章能夠給你帶來一些靈感或者思路。


4. 總結

回到文章開頭的新聞。新聞裡提到的 Google L3 級別,其實面向的是實習生或應屆生的測試職位,考察的演算法也是比較基礎和模式化的問題,更不會涉及複雜的系統設計問題(但薪水也有 18.3 萬美元,果然宇宙的盡頭是外企)。

讓我意外的是,在 OpenAI 的 GPT-4 技術報告中,GPT-4 在 LeetCode 演算法上的測試資料表現非常糟糕。如果以 GPT-4 的水平是不可能透過 Google 的演算法面試的,更不用說該新聞發表日期時的 ChatGPT 應該還在用 GPT-3.5 模型。

這個新聞的可信度很低。

GPT-4 技術報告:https://cdn.openai.com/papers/gpt-4.pdf

總結一下:

  • 1、ChatGPT 能夠解決 “資訊量太大 ”而 “注意力太少” 的矛盾,每個人的延展性將被極大擴充套件;
  • 2、ChatGPT 確實有總結提煉的能力,但對問題的深度拆解和建構能力,ChatGPT 無法做倒;
  • 3、將思考的權利讓渡給 AI 是危險的,越是折磨大腦皮層的過程越不能讓渡給 AI;
  • 4、我們的對手不是 AI,而是比你更懂控制 AI 的人。

最後,希望大家在學習演算法的道路上共勉,小彭等拿到 Guardian 牌子後來回來還願 ?。

你認為 ChatGPT 技術是否被過度炒作?你對這個問題有什麼見解?歡迎聊聊你的看,也歡迎你轉發、留言、在看,給我一個反饋喔。


ChatGPT 實驗資料

參考資料

相關文章