題目描述
多級雙向鏈表中,除了指向下一個節點和前一個接待你指針之外,它還有一個子鏈表指針,可能指向單獨的雙向鏈表。這些子鏈表也可能會有一個或多個自己的子項,依此類推,生成多級數據結構,如下面的示例所示。
給你位於列表第一級的頭節點,請你扁平化列表,使所有節點出現在單極雙鏈表中。
示例1:
輸入: head = [1, 2, 3, 4, 5, 6, null, null, null, 7, 8, 9, 10, null, null, 11, 12]
輸出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
解釋:
** 圖1**
示例2:
輸入: head = []
輸出: []
說明:
- 節點數目不超過1000
1 <= node.val < 10E5
思路分析
我們看到題幹首先想到的是,深度優先搜索算法,所以我們直接藉助棧stack
保存具有child
非空指針後的節點,當深度遍歷完之後,從stack
中彈出保存點,接着遍歷。
圖2
我們通過圖2可知,設遍歷指針爲curr
,紅色箭頭爲curr
的遍歷軌跡:
- 當存在
child
節點時,將curr.next
壓入棧中,直接遍歷curr.child
; - 當在下沉過程中,又檢測到
child
節點,則重複步驟1; - 在最後一級鏈表到盡頭時,檢測棧是否爲空:不爲空則彈出棧頂元素(返回上一級鏈表);爲空則完成多級鏈表的遍歷,直接輸出結果
output
.
解題步驟
- 初始化兩個分區指針
oddTail, evenTail
和布爾變量isOddNode
; - 遍歷原始鏈表,根據
isOddNode
判斷evenTail.next
是否插入奇數分區; - 當
evenTail.next == null
時停止並返回head
.
解題代碼
public static ListNode solution(ListNode head) {
if (head == null) {
return head;
}
/* Step1: Init. pointers */
Stack<ListNode> stack = new Stack<>();
ListNode curr = head;
/* Step2: go through the head-list
and
go back last level when no more subsequent child and next nodes
*/
while (curr != null) {
// exists child-node
if (curr.child != null) {
ListNode node = curr.next;
stack.push(node);
curr.next = curr.child;
}
// back to last level
if (curr.next == null && !stack.isEmpty()) {
curr.next = stack.peek();
curr = stack.pop();
}
curr = curr == null ? null : curr.next;
}
/* Step3: return head */
return head;
}
複雜度分析
時間複雜度:我們對原始鏈表進行了一次遍歷,容易理解時間複雜度爲O(N)
;
空間複雜度:我們這裏設置了輔助容器stack
,故空間複雜度爲O(N)
.
GitHub源碼
完整可運行文件請訪問GitHub。