您将获得一个双向链表,除了下一个和前一个指针之外,它还有一个子指针,可能指向单独的双向链表。这些子列表可能有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。
扁平化列表,使所有结点出现在单级双链表中。您将获得列表第一级的头部。
示例:
输入:
1---2---3---4---5---6--NULL
|
7---8---9---10--NULL
|
11--12--NULL
输出:
1-2-3-7-8-11-12-9-10-4-5-6-NULL
以上示例的说明:
给出以下多级双向链表:
我们应该返回如下所示的扁平双向链表:
思路分析:不难发现,当head存在child时,优先访问child(递归),访问完child需要回到head的next。明显的不要不要的递归访问,所以采取stack进行辅助。
/*
// Definition for a Node.
class Node {
public:
int val;
Node* prev;
Node* next;
Node* child;
Node() {}
Node(int _val, Node* _prev, Node* _next, Node* _child) {
val = _val;
prev = _prev;
next = _next;
child = _child;
}
};
*/
class Solution {
public:
Node* flatten(Node* head) {
stack<Node*> myStack;//辅助队列,当当前head存在child时,保存head->next的现场
//resListHead结果链表的头部,resListEnd结果链表的尾部
Node *resListHead = head, *resListEnd = head;
if (head == NULL){
return resListHead;
}
//第一个节点特殊处理
if (head->child != NULL){
//当前head存在child。需要保存head->next的现场
if (head->next != NULL){
myStack.push(head->next);
}
head = head->child;//并且转移到child
resListEnd->child = NULL;//结果链表节点所有的child指针域都得置空
}
else{
head = head->next;//否则直接转入到next
}
//循环处理剩余的节点
while (head != NULL || !myStack.empty()){
if (head == NULL){//如果当前已经到达了某个子链的尾端
head = myStack.top();//恢复上次保存的next现场
myStack.pop();
}
//将head链接到resListEnd的尾部
head->prev = resListEnd;
resListEnd->next = head;
resListEnd = resListEnd->next;
//分head是否有child转移到不同的现场
if (head->child != NULL){
//当前head存在child。需要保存head->next的现场
if (head->next != NULL){
myStack.push(head->next);
}
//转移现场至head的child
head = head->child;
resListEnd->child = NULL;//结果链表节点所有的child指针域都得置空
}
else{//不存在child,直接访问
head = head->next;//转移现场至head的next
}
}
//!!!最后需要封尾
if (resListEnd != NULL){
resListEnd->next = NULL;
}
return resListHead;
}
};
方法二:直接递归扁平化。
/*
// Definition for a Node.
class Node {
public:
int val;
Node* prev;
Node* next;
Node* child;
Node() {}
Node(int _val, Node* _prev, Node* _next, Node* _child) {
val = _val;
prev = _prev;
next = _next;
child = _child;
}
};
*/
class Solution {
public:
Node* flatten(Node* head) {
if (head == NULL){
return NULL;
}
Node *startHeadNext = NULL, *startChild = head;
//第一步:寻找到第一个有child的节点
while (startChild != NULL && startChild ->child == NULL){
startChild = startChild->next;
}
if (startChild == NULL){//如果此段链表都没child,直接返回
return head;
}
//第二步:递归扁平化startChild的next
startHeadNext = flatten(startChild->next);
startChild->next = NULL;
//第三步:然后扁平化startChild的child
Node *startHeadChild = flatten(startChild->child);
//第四步:将startHeadChild连接到startChild的尾部
startChild->next = startHeadChild;
startHeadChild->prev = startChild;
startChild->child = NULL;
//第五步:将startHeadNext连接到startChild的尾部
if (startHeadNext != NULL){
Node *nowHeadTail = getTail(startChild);//获取startChild的尾部节点
startHeadNext->prev = nowHeadTail;
nowHeadTail->next = startHeadNext;
}
return head;
}
//返回head链表的尾部节点
Node *getTail(Node *head){
while (head != NULL && head->next != NULL){
head = head->next;
}
return head;
}
};