面试题 26(*),复杂链表的复制(思路很新颖,把每个复制出来的结点连到原结点后面,再把偶数位结点拆出,时间复杂度O(N)且不需要额外空间)

我的思路是先创建新链表,新链表的m_pSibling指针暂时不赋值,创建的过程中用hashmap存放旧结点和新结点的映射。然后再遍历一遍原链表,同时利用hashmap给新链表的m_pSibling赋值。

时间复杂度是O(N),但是需要额外的存储空间来定义hashmap。

更好的方式想了很久也没想出来。

书中给出了时间复杂度是O(N)且不需要额外存储空间的方法。

假设原链表如图:

第一步:将每个结点复制,但是复制出来的新结点直接加到老结点的m_pNext上,相当于把新结点插入了旧链表。

第二步:设置新结点的m_pSibling,这一步很关键。我的方法之所以要定义hashmap,就是因为新创建出来的结点的m_pSibling如果要赋值,我们不知道原链表的结点对应新链表的哪个结点,为了找到对应的结点,要么遍历一遍,要么事先存好,一个耗额外的时间,一个耗额外的空间。

在这个方法中,因为新结点就在原结点的下一个,所以原结点的m_pSibing结点的下一个结点就是新结点m_pSibing应该指向的结点。

第三步:拆链。把偶数位的结点拆出来组成新链表。

我的代码,时间原因,没有测过。

ComplexListNode * cloneLinkedList(ComplexListNode *pHead){
    if(NULL == pHead){
        return NULL;
    }
    
    //Clone every node
    ComplexListNode *node = pHead;
    while(node != NULL){
        CompleListNode *clonedNode = new ComplexListNode();
        clonedNode -> m_nValue = node -> m_nValue;
        clonedNode -> m_pNext = node -> m_pNext;
        clonedNode -> m_pSibling = NULL;
        
        node -> m_pNext = clonedNode;
        node = clonedNode -> m_pNext;
    }
    
    //set the value of m_pSibling of each node
    node = pHead;
    int count = 0;
    while(NULL != node){
        count ++;
        if(count%2){
            if(NULL == node -> m_pSibling){
                node -> m_pNext -> m_pSibling = NULL;
            }else{
                node -> m_pNext -> m_pSibling = node -> m_pSibling -> m_pNext;
            }
        }
    }
    
    //seperate the new linked list from orginal lsit.
    ComplexListNode *clonedHead = pHead -> m_pNext;
    ComplexListNode *clonedNode = pHead -> m_pNext;
    pHead -> m_pNext = clonedNode -> m_pNext;
    node = clonedNode -> m_pNext;

    while(NULL != node){
        clonedNode -> m_pNext = node -> m_pNext;
        clonedNode = cloneNode -> m_pNext;
        node -> m_pNext = clonedNode -> m_pNext;
        node = node -> m_pNext;
    }
    return clonedHead;
}

 

补充:

Leetcode上也有类似的一题,

Copy List with Random Pointer

http://oj.leetcode.com/problems/copy-list-with-random-pointer/

我的代码(白板一遍AC):

/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     RandomListNode *next, *random;
 *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    /**
     * Solution(1) use map to map new node and ori node, time complexity O(n), space complexity O(n)
     * Solution(2) put the new copied list after the tail of ori list, when copying the pointer, traverse n nodes to find the mapped new node. time complexity O(n2), space complexity O(1)
     * Solution(3) put the new copied node after each ori node, when copying the pointer, next node of ori node is the new node. After copy, retrieve every node on even number'th place, form a new list. time complexity O(n), space complexity O(1).
     * Here is the code for Solution (3)
    */
    RandomListNode *copyRandomList(RandomListNode *head) {
        if(NULL == head) return NULL;
        
        for(RandomListNode* p = head; p != NULL; p = p -> next){
            RandomListNode* cNode = new RandomListNode(p -> label);
            cNode -> next = p -> next;
            p -> next = cNode;
            p = cNode;
        }
        for(RandomListNode* q = head; q != NULL; q = q -> next){
            RandomListNode* temp = q -> next;
            temp -> random = (q -> random == NULL ? NULL : q -> random -> next);
            q = temp;
        }
        RandomListNode* p1 = head; RandomListNode* p2 = head -> next;
        RandomListNode* secHead = p2;
        while(p1 != NULL){
            p1 -> next = p2 -> next;
            if(p2 -> next != NULL)
                p2 -> next = p2 -> next -> next;
            p1 = p1 -> next;
            p2 = p2 -> next;
        }
        return secHead;
    }
};

 

 

书上代码:

// 《剑指Offer——名企面试官精讲典型编程题》代码
// 著作权所有者:何海涛

#include "stdafx.h"
#include "ComplexList.h"

void CloneNodes(ComplexListNode* pHead);
void ConnectSiblingNodes(ComplexListNode* pHead);
ComplexListNode* ReconnectNodes(ComplexListNode* pHead);

ComplexListNode* Clone(ComplexListNode* pHead)
{
    CloneNodes(pHead);
    ConnectSiblingNodes(pHead);
    return ReconnectNodes(pHead);
}

void CloneNodes(ComplexListNode* pHead)
{
    ComplexListNode* pNode = pHead;
    while(pNode != NULL)
    {
        ComplexListNode* pCloned = new ComplexListNode();
        pCloned->m_nValue = pNode->m_nValue;
        pCloned->m_pNext = pNode->m_pNext;
        pCloned->m_pSibling = NULL;
 
        pNode->m_pNext = pCloned;
 
        pNode = pCloned->m_pNext;
    }
}

void ConnectSiblingNodes(ComplexListNode* pHead)
{
    ComplexListNode* pNode = pHead;
    while(pNode != NULL)
    {
        ComplexListNode* pCloned = pNode->m_pNext;
        if(pNode->m_pSibling != NULL)
        {
            pCloned->m_pSibling = pNode->m_pSibling->m_pNext;
        }
 
        pNode = pCloned->m_pNext;
    }
}

ComplexListNode* ReconnectNodes(ComplexListNode* pHead)
{
    ComplexListNode* pNode = pHead;
    ComplexListNode* pClonedHead = NULL;
    ComplexListNode* pClonedNode = NULL;
 
    if(pNode != NULL)
    {
        pClonedHead = pClonedNode = pNode->m_pNext;
        pNode->m_pNext = pClonedNode->m_pNext;
        pNode = pNode->m_pNext;
    }
 
    while(pNode != NULL)
    {
        pClonedNode->m_pNext = pNode->m_pNext;
        pClonedNode = pClonedNode->m_pNext;
 
        pNode->m_pNext = pClonedNode->m_pNext;
        pNode = pNode->m_pNext;
    }
 
    return pClonedHead;
}

 

 

posted on 2014-01-21 08:19  Felix Fang  阅读(311)  评论(0)    收藏  举报

导航