复杂链表的复制

题目

  请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表,在复杂链表中,每个结点除了有一个pNext指针指向下一个结点之外,还有一个pSibling指向链表中的任意结点或者NULL。

思路

方法一

  复制原始链表上的每一个结点,并通过pNext连接起来;然后再设置每个结点的pSibling指针。

假设原始链表中某个结点N的pSibling指针指向结点S,那么就需要从头到尾遍历查找结点S,如果从原始链表的头指针开始,经过m步之后达到结点S,那么在复制链表中的结点N'的pSibling指针指向的结点也是距离复制链表s步的结点。通过这种办法就可以为复制链表上的每个结点设置pSibling指针。

时间复杂度:O(N^2)

方法二

  方法1是通过链表查找来得到pSibling指针所指向的结点,实际上我们可以通过空间换取时间,将原始链表和复制链表的结点通过哈希表对应起来,这样查找的时间就从O(N)变为O(1)。具体如下:

复制原始链表上的每个结点N创建N',然后把这些创建出来的结点用pNext连接起来。同时把<N,N'>的配对信息方法一个哈希表中;然后设置复制链表中的每个结点的pSibling指针,如果原始链表中结点N的pSibling指向结点S,那么在复制链表中,对应的N'应该指向S'。

时间复杂度:O(N)

方法三

  在不使用辅助空间的情况下实现O(N)的时间效率。

  1. 根据原始链表的每个结点N创建对应的N',然后将N‘通过pNext接到N的后面;
  2. 设置复制出来的结点的pSibling。假设原始链表上的N的pSibling指向结点S,那么其对应复制出来的N'是N->pNext指向的结点,同样S'也是结点S->pNext指向的结点。
  3. 把长链表拆分成两个链表,把奇数位置的结点用pNext连接起来的就是原始链表,把偶数位置的结点通过pNext连接起来的就是复制链表。

hash方法

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {    
public:
    Node* copyRandomList(Node* head) {
        if (head == nullptr) {
            return nullptr;
        }

        map<Node *, Node *> MAP;
        Node *tmp = head;
        while (tmp != nullptr) {
            MAP[tmp] = new Node(tmp->val);
            tmp = tmp->next;
        }

        tmp = head;
        while (tmp != nullptr) {
            MAP[tmp]->next = MAP[tmp->next];
            MAP[tmp]->random = MAP[tmp->random];
            tmp = tmp->next;
        }
        return MAP[head];
    }
};

复制连接的方法

#include <iostream>
using namespace std;

struct node
{
    int data;
    struct node *next,*sibling;
};
class Solution
{
    public:
        Solution();
        void create();
        void print();
        
        node *clone(node *head);
        void clone_node(node *head);
        void con_sib_node(node *head);
        node *recon_node(node *head);
        node *head;
};
Solution::Solution()
{
    head=new node();
    head->next=nullptr;
    head->sibling=nullptr;
    head->data=0;
}
void Solution::create()
{
    if(head==nullptr)
        return;
    auto t=head;
    int x;
    while(1)
    {
        cin>>x;
        if(x)
        {
            t->next=new node();
            t=t->next;
            t->sibling=nullptr;
            t->data=x;
            t->next=nullptr;
        }
        else
        {
            t->next=nullptr;
            t->sibling=nullptr;
            break;
        }
    }
} 
void Solution::print()
{
    auto n=head->next;
    while(n)
    {
        cout<<n->data<<endl;
        n=n->next;
    }
}
node *Solution::clone(node *head)
{
    clone_node(head);
    con_sib_node(head);
    return recon_node(head);
}
void Solution::clone_node(node *head)
{
    node *n=head->next;
    while(n)
    {
        node *clone=new node();
        clone->data=n->data;
        clone->next=n->next;
        clone->sibling=nullptr;
        
        n->next=clone;
        n=clone->next;
    }
}
void Solution::con_sib_node(node *head)
{
    node *n=head->next;
    while(n)
    {
        node *clone=n->next;
        if(n->sibling)
            clone->sibling=n->sibling->next;
        n=clone->next;
    }
}
node *Solution::recon_node(node *head)
{
    node *n=head->next;
    node *h_clone=nullptr;
    node *n_clone=nullptr;
    
    if(n)
    {
        h_clone=n_clone=n->next;
        n->next=n_clone->next;
        n=n->next;
    }
    while(n)
    {
        n_clone->next=n->next;
        n_clone=n_clone->next;
        
        n->next=n_clone->next;
        n=n->next;
    }
    return h_clone;
}
int main() 
{
    Solution s;
    s.create();
     
    node *h=s.clone(s.head);
    return 0;
}

 

posted on 2019-01-01 15:23  tianzeng  阅读(195)  评论(0编辑  收藏  举报

导航