LeetCode 89,因為題目晦澀而被點了1500+反對的搜索問題


本文始發於個人公眾號:TechFlow,原創不易,求個關注


今天是LeetCode專題第55篇文章,我們一起來看看LeetCode中的第89題 Gray Code(格雷碼)。

這題的官方難度是Medium,通過率是48.9%,點贊639,反對1545。又是一道反對比點贊多得多的題目,我個人發現其實這些反對很多的題目都有一個特點,就是題意比較晦澀,出題人的意圖不太容易get到。不知道是不是老外理解能力不太行,所以都給出了這么多的反對。

我們就來看看這道題的真面目吧。

題意

題目中說gray code,格雷碼是一連串n位二進制表示的數字。這一串的數字有一個特點就是第一個數字是0,從0開始后面的每一個數字和前一個數字只有一個二進制位不同。

題目會給定我們一個非負整數n,要求我們生產n位的灰色代碼,也就是產生這些數字。並且這些數字是以10進制存儲的。

不知道大家看明白沒有,我們來看一個樣例。

樣例

Input: 2
Output: [0,1,3,2] 

在上面這個例子當中,輸入是2,表示這些數字是兩位二進制位構成的,輸出是[0, 1, 3, 2]。我們把0,1,3,2翻譯成二進制,0是00,1是01,3是11,2是10。排列在一起的話就是00, 01, 11, 10。我們可以發現每一個數和前一個數相差的都是一個二進制位。

題目當中相關的描述就這么多,但其實有很多隱藏的信息沒有給,要我們自己猜測。比如說每一個數字只能出現一次,不然的話這個序列就是無窮無盡的。另外一個隱藏信息是,這樣的序列應該也不是唯一的,但是題目並沒有說是否所有合法的序列都可以通過測試,還是說一定要返回字典序最小的結果。

題目比較晦澀也就算了,這些隱藏信息沒有交代清楚,也難怪大家會費解。

題解

當然以上的問題其實也不是事,我們不確定試一次也就知道了,核心還是怎么想出解法來。

干想是沒有結果的,還是要先分析搜集一些信息。首先,題目給定的n,限制了每個數能夠使用的二進制位的數量。n個二進制位一共能表示的數字有$2^n$種,我們無法得知是否這么多數字都能串聯起來。假設可行的話,那么這個問題其實就是這$2^n$個數如何擺放的問題。

所以問題的關鍵就是要尋找這樣一個序列,根據我們之前解全排列以及各種排列的方法,可以聯想得到,這大概率是一個搜索問題。

順着搜索的思路繼續往下,剩下的事情就容易了,我們的起始搜索點是0。題目中要求了每兩個相鄰的數的二進制位只相差一個,那么我們可以遍歷這些二進制位,尋找0的后繼節點。同樣對於每一個后繼節點來說,我們都可以用同樣的方法尋找它的后繼們。再加上gray code不能包含重復的元素,我們可以在搜索的時候加上剪枝。

這一套其實是一個經典的搜索問題的流程。

如果我們換個思路,雖然也能得到一樣的解法,但是思考的過程會不太一樣。怎么換思路呢,其實也簡單,我們把它想象成一個圖論問題。也就是說,每一個數字都是圖中的一個節點。如果兩個數字之間滿足只相差了一個二進制位,那么說明它們之間有一條邊相連。整個問題就轉變成了我們從0這個點出發,找出所有連通的節點。

對於圖上的遍歷問題,方法就很固定了就是搜索。也就是說從這個角度思考的話,更加容易想到搜索上面了, 整個思考的鏈路會更短。這也是為什么很多大神建模的時候喜歡從往圖上考慮的原因。

這些都想明白了再來寫代碼真的就水到渠成了,整個核心代碼真的不長:

class Solution:
 def grayCode(self, n: int) -> List[int]:  ret = [0]  elements = {0}   def dfs(cur):  # 遍歷與cur唯一不同的二進制位  for i in range(n):  # 針對這一維做亦或,將0變1,1變0  nxt = cur ^ (1 << i)  if nxt in elements:  continue  # 記錄答案,繼續往下遍歷  elements.add(nxt)  ret.append(nxt)  dfs(nxt)  dfs(0)  return ret 

總結

單純從思路以及最后的AC代碼來看的話,這道題難度應該是很低的,實際上也的確如此,這題的通過率接近50%,已經是Medium難度的下屆了。但是相比於做對這題而言,更加重要的是思路。以圖論的思維來抽象建模是算法題當中一個非常常見的手段,這是比題目本身更加寶貴的東西。

如果你讀過昨天的文章的話,會發現昨天的87題,本質上也是用的一個圖論建模的方法。但是從表現形式上來說,這兩題真的可以說是完全不一樣。建議大家能好好做做這兩題,體會一下其中思維和解法的閃光點。

今天的文章到這里就結束了,如果喜歡本文的話,請來一波素質三連,給我一點支持吧(關注、轉發、點贊)。

本文使用 mdnice 排版


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM