題目連結:
題目意譯:
在一個無限延伸的二元樹中,其中每個節點都有兩個小孩,而這些節點是以一列一列的順序來編號。
在奇數編號列(即,第一、三、五、……),編號順序將會是從左至右;而偶數編號列(第二、四、六、……),編號順序將會是從右至左。
給定在這棵樹中某個節點的編號,回傳從根節點到這個節點的路徑上所有經過的節點之編號。
限制:
1 ≦ label ≦ 10 ^ 6
範例測資:
範例 1:
輸入: label = 14
輸出: [1,3,4,14]
範例 2:
輸入: label = 26
輸出: [1,2,6,10,26]
解題思維:
首先,我們可以看到奇數列(層)的編號跟
這題提及的編號方式是一致的。只有偶數層需要轉換。
可以看到如果編號方式統一由左至右,則每一個節點(假設編號為 i)會滿足一個特性:
2i 和 2i + 1 會分別是其左小孩和右小孩的編號且 i ÷ 2 取整數將會是其父母節點的編號(除了根節點以外)。
(這個特性在上面連結的那一題也有提過)
因此我們可以先把給定的 label 轉換成「正常」的編號(即統一由左至右),然後就一直將編號除 2 取整數便可以知道根節點到給定的節點的路徑上所有節點的「正常」編號。最後再把編號轉完本題的格式即是所求。
那要怎麼在「正常」編號和本題的編號之間互轉呢?首先把欲轉換的編號 x 一直除以 2 取整數,看可以除幾次才會到 1。其實就跟上面的步驟一樣,只是這是為了看 x 在第幾列(假設在第 c 列,其中 c 跟題目敘述一樣是從 1 開始數)。
如果 c 是奇數,則編號不變;如果是偶數,則我們可以看到「正常」和本題的編號是彼此鏡射的,因此套入
(2 ^ c - x - 1) + 2 ^ (c - 1)
即可轉換成對方,其中後面 2 ^ (c - 1) 是該列中最小的編號(基準值)、而前面的 (2 ^ c - x - 1) 則是為了計算 x 與該列最後一個「正常」編號之值距離多遠,這樣便可以得到鏡射後的數字離該列第一個數字多遠。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。