合并升序列表
递归法
当其中一个链表为空时,直接返回另一个。当都不空,假设除较小的头节点外都已合并,则只需要把头结点与以排列好的的头相连。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
if(list1==nullptr)
return list2;
if(list2==nullptr)
return list1;
if(list1->val<=list2->val)
{
list1->next=mergeTwoLists(list1->next,list2);
return list1;
}
else
{
list2->next=mergeTwoLists(list1,list2->next);
return list2;
}
}
};
扁平化多级双向链表
递归法
每个结点有两种一般情况:有child,无child。
在无child时,我们只要将头结点之后的结点扁平化。
有child时,我们需要分别将child及其后的链表和next及其后的链表扁平化,然后找到child扁平化后的最后一个节点,将其与next扁平后的第一个节点连接,并删除原来的child。注意next及其后的链表为空的情况。
class Solution {
public:
Node* flatten(Node* head) {
Node *t1,*t2,*t3;
if(head==NULL||(head->next==NULL&&head->child==NULL))
return head;
if(head->child==NULL)
{
head->next=flatten(head->next);
}
else
{
t1=flatten(head->next);
t2=flatten(head->child);
head->child=NULL;
head->next=t2;
t2->prev=head;
t3=head;
while(t3->next!=NULL)
t3=t3->next;
if(t1!=NULL)
{
t3->next=t1;
t1->prev=t3;
}
}
return head;
}
};
复制带随机指针的链表
问题描述:
给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。
注意是深拷贝,也就是说新链表不能使用任何原链表中的指针。
先拷贝一条单链表,这只需要按顺序new一个节点并复制每个节点的数据元素就可以了。
然后我们用a1指针遍历原链表,用a2指针指向每个对应的random。a2存在两种情况:顺着next可以到达a1;顺着a2可以到达链表末尾(NULL)。让a2顺着next遍历下去,直到遇到a1或者走完链表,记录下步数i。为了区分两种步数,第二种步数乘上一个-1。
正的i代表random指向该节点的前i个节点,负的i代表random指向整个链表的倒数第i个节点。
最后通过一组间隔为i的双指针找行链表中的对应节点。
class Solution {
public:
Node* copyRandomList(Node* head) {
if(head==NULL)
return NULL;
Node *a1,*a2,*b1,*b2,*b3,*newhead;
newhead=new Node(head->val);
a1=head;a2=head->next;
b1=newhead;
while(a2!=NULL)
{
b2=new Node(a2->val);
b1->next=b2;
a1=a1->next;
b1=b1->next;
a2=a1->next;
}//复制单链表
a1=head;b1=newhead;
int i=0;
while(a1!=NULL)
{
a2=a1->random;
if(a2==NULL)
{
b1->random=NULL;
a1=a1->next;
b1=b1->next;
continue;
}
i=0;
while(a2!=a1&&a2!=NULL)
{
a2=a2->next;
i++;
}
if(a2==NULL)
i*=-1;//找到间隔i
a1=a1->next;
if(i>=0)
{
b2=newhead;b3=newhead;
for(int j=0;j<i;j++)
b3=b3->next;
while(b3!=b1)
{
b2=b2->next;
b3=b3->next;
}
b1->random=b2;
}
else
{
b2=b1;b3=b1;
for(int j=0;j>i;j--)
b3=b3->next;
while(b3!=NULL)
{
b2=b2->next;
b3=b3->next;
}
b1->random=b2;
}
b1=b1->next;
}
return newhead;
}
};