我要去假設有在你上面的示例輸出一個錯誤,它確實應該:
{ 1 [3 1 1] 2 [1 1] 3 [] 4 [1] 5 [] 6 [] }
你的樣品輸出沒有考慮一個事實,即6是一個曾孫1和2的孫子。
我會在這裏詳細介紹一個解決方案。我們將通過編寫針對指定了一棵樹,在樹的頂點,一個功能開始時,計算到樹的頂部從頂點的路徑:
(defn path-to-top [tree v]
(if (nil? v)
'()
(cons v (path-to-top tree (:root (get tree v))))))
接下來,讓我們寫一個函數需要從頂點到樹和同事每個頂點的頂部這樣的路徑上這個頂點的距離開始頂點:
(defn steps-indexed-path
([upward-path steps]
(if (= upward-path '())
'()
(cons [(first upward-path) steps] (steps-indexed-path (rest upward-path) (+ steps 1)))))
([upward-path]
(steps-indexed-path upward-path 0)))
當第一函數返回的頂點列表,這個功能返回一個向量的列表,其中第一個條目是一個頂點,第二個條目是來自第一個條目的步驟數指向頂點的路徑上的第一個頂點。
好吧,當我們在樹中應用此功能,每個頂點,我們將(在某些嵌套形式),每個頂點v
和每個後代的w
v
數據[v <# steps from v to w>]
。對於這些數據中的每一個,我們應該在我們的最終解決方案中將與v
相關的向量的<# steps from v to w>
分量加1。在我們繼續之前的矢量階段,我們只是準水平與計數:
(defn count-descendants [tree]
(let [markers (reduce concat '() (map steps-indexed-path (map (partial path-to-top tree) (keys tree))))]
(reduce (fn [counter [vertex generation]] (assoc counter vertex (assoc (get counter vertex {}) generation (+ (get (get counter vertex {}) generation 0) 1)))) {} markers)))
這將產生一個hash-map
,它的鍵是v
頂點並使得每個頂點對應的v
的值是另一個hash-map
其中鍵是樹中頂點的不同可能世代的後代,並且值是每一代的後代數。
現在我們所要做的就是把以前的函數的輸出到您指定的格式:
(defn sanitize-descendant-counts [association]
(let [max-depth (apply max (keys association))]
(map (fn [i] (get association i 0)) (range 1 (+ max-depth 1)))))
(defn solve-problem [tree]
(let [descendant-counts (count-descendants tree)]
(apply merge (map (fn [v] (hash-map v (vec (sanitize-descendant-counts (get descendant-counts v))))) (keys descendant-counts)))))
這是我得到的輸出,當我運行你的例子此代碼:
{1 [3 1 1], 4 [1], 6 [], 3 [], 2 [1 1], 5 []}
您可以access all the code here,包括你需要在你的榜樣運行什麼。希望有所幫助!
不知道我理解你的樹形表示。 ':root'和':parent'鍵代表什麼?我只希望找到每個節點的直接父節點,爲什麼還需要一個額外的密鑰? –
這是一個錯字,關鍵是「:根」。每個節點都有一個對其父(根)的引用。謝謝! – user1067437