2013-03-06 48 views
5

我需要用下一個和隨機指針複製一個鏈表。下一個指針和通常一樣指向鏈表中的下一個元素,隨機指針可能指向任何其他節點,甚至指向其自身。 如果我不允許在任何時候修改給定的列表,那麼如何完成這項工作,只列出閱讀權限。用下一個和隨機指針複製一個鏈表,在列表中只給出讀取權限

+1

要麼我失去了一些東西,或者你的問題的描述是失去了一些東西。當然,如果你已經讀取了原始列表和下一個指針,你只需從列表頭開始,複製該節點並按照下一個指針 - 完成? – us2012 2013-03-06 06:42:12

+1

@ us2012我認爲您應該正確初始化這些「隨機」指針,以便它們指向新列表的節點而不是原始列表的節點。所以,這不是一個完整的節點副本,您需要在每個節點中更改兩個指針。 – 2013-03-06 06:47:40

+0

@Alexey啊!是的,這更有意義。 – us2012 2013-03-06 06:49:53

回答

12

最簡單的解決辦法是這樣的......

您遍歷原來的鏈表,創建另一個鏈表,其節點是一樣的,在最初的名單,在適當的next指針,指向新列表的相應節點。您現在保留random指針。

在遍歷列表時,您還將舊列表的節點地址/指針和新列表的節點地址/指針放到associative array(AKA映射,散列表等)中,其中舊列表的節點地址/指針是key,新列表的節點地址/指針是value

然後就遍歷新的列表以及與所述value從對應於key等於random指針關聯數組的每個節點替換random指針。

散列表可以用作關聯數組來實現與原始列表中元素數量成比例的時間和內存成本。

時間&該解決方案的空間複雜度分別爲O(n)。

+0

是的,很好。看看是否有解決方案,'O(n)'是嚴格的而不是分期付款的! – us2012 2013-03-06 07:06:57

+1

+1。在接受微軟採訪時,我給出了與@Max相同的答案(在舊節點之間插入節點,然後.......)。但他們明確要求我使用HashMap解決問題。預計Alexey Frunze給出的確切解決方案。不知何故,我到了相同的答案。 – Trying 2013-09-18 03:15:40

1
struct node * copy(struct node * head) 
{ 
    struct node *dummy; 
    struct node *dummy1=dummy; 
    struct node *head1=head; 

    struct node *map[1000000]; 
    while(head) { 
     dummy->next=new struct node; 
     map[head]=dummy->next; 
     dummy->next->data=head->data; 
     dummy=dummy->next; 
     head=head->next 
    } 
    dummy=dummy1; 
    head=head1; 
    while(head){ 
     dummy->next->arb=map[head->arb]; 
     dummy=dummy->next; 
     head=head->next; 
    } 
    return dummy1->next; 
} 
+7

歡迎來到Stack Overflow。你可能想要添加一些關於你的答案爲什麼和如何工作的解釋。 (無論是文本還是代碼註釋)。所以OP可以從中學習。 – Oren 2013-03-30 21:06:34

14

優雅溶液(線性時間,常數空間):

創建節點1,2,3的副本... n和1和2,2和3等之間插入它們,忽略現在爲random字段。因此列表中總共有2n個節點。

現在的單程設置random字段的值,在新的節點通過以下方式:

original.next.random = original.random.next 

這工作,因爲LHS是在新創建的節點的random領域,RHS是指向任意節點的副本,正是我們想要的。

現在通過一次性恢復原始鏈接列表並返回新列表。

original.next = original.next.next; 
copy.next = copy.next.next; 

溶液從here.

+2

原始列表爲只讀的限制條件如何? – 2013-09-18 04:14:50

+0

@AlexeyFrunze哦,是的,那麼它不會工作。沒有看到這個限制... – Max 2013-10-14 07:30:21

0
#include<stdlib.h> 
#include<stdio.h> 

typedef struct node_s{ 
int data; 
struct node_s *next; 
struct node_s *arbit; 
} Node_s; 

void free_list(Node_s * head){ 
if(!head) return; 
Node_s * temp = head; 
Node_s * next = head; 
while(temp){ 
    next = temp->next; 
    free(temp); 
    temp = next; 
} 
} 
void push_1(Node_s **head, int value){ 
if(*head == NULL){ 
    (*head) = (Node_s *)malloc(sizeof(Node_s)); 
    (*head)->data = value; 
    (*head)->next = NULL; 
} 
else{ 
    Node_s * temp = (Node_s *)malloc(sizeof(Node_s)); 
    if(temp){ 
     temp->data = value; 
     temp->next = (*head); 
     *head = temp; 
    } 
} 
} 
void add_arbit(Node_s *L1, int a, int b){ 
Node_s * first = L1; 
Node_s * second = L1; 

while(first){ 
    if(first->data == a) 
     break; 
    first = first->next; 
} 
while(second){ 
    if(second->data == b) 
     break; 
    second = second->next; 
} 
if(first) 
    first->arbit = second; 
} 
Node_s * create_node(int val){ 

Node_s * temp = (Node_s *)malloc(sizeof(Node_s)); 
if(temp){ 
    temp->data = val; 
    temp->next = NULL; 
} 
return temp; 
} 

Node_s * clone(Node_s * node){ 

if(!node) return NULL; 
Node_s * current = node; 

//First insert clone nodes in original linked list.  
while(current){ 
    Node_s * current_next = current->next; 
    current->next = create_node(current->data); 
    current->next->next = current_next; 
    current = current_next; 
} 
current = node; 

//Now copy arbit pointer of each node to cloned list 
Node_s * clone_head = current->next; 
while(current){ 
    Node_s * clone = current->next; 
    if(current->arbit){ 
     clone->arbit = current->arbit->next; 
    } 
    current = clone->next; 
} 

current = node; 

//Segregate two linked list 
while(current){ 
    Node_s * clone = current->next; 
    current->next = clone->next; 
    if(clone->next){ 
     clone->next = clone->next->next; 
    } 
    current = current->next; 
} 
//return head pointer to the calling function 
return clone_head; 
} 

int main(){ 
Node_s * L1 = NULL; 
push_1(&L1,1); 
push_1(&L1,2); 
push_1(&L1,3); 
push_1(&L1,4); 
push_1(&L1,5); 
push_1(&L1,6); 

add_arbit(L1,1,6); 
add_arbit(L1,2,5); 
add_arbit(L1,3,1); 
add_arbit(L1,4,2); 
add_arbit(L1,5,4); 
add_arbit(L1,6,3); 

print_list_1(L1); 

Node_s *clone_head = clone(L1); 
free_list(L1); 
print_list_1(clone_head); 

return 0;  
} 
+2

這段代碼是非常複雜的,沒有對這段代碼的評論是沒有道理的。請留下一些關於此代碼如何工作的意見或解釋,以及如何證明您爲此做出的設計選擇。 – rayryeng 2014-08-30 15:40:00

0

這裏採取的是遞歸的解決方案(在Java中):

public class Solution { 

    public HashMap<RandomListNode, RandomListNode> createdNode; 
    public RandomListNode copyRandomList(RandomListNode head) { 
     createdNode = new HashMap<RandomListNode, RandomListNode>(); 
     return cc(head); 
    } 

    private RandomListNode cc(RandomListNode node) { 
     if(node == null) 
     { 
      return null; 
     } 

     RandomListNode newNode = new RandomListNode(node.label); 

     createdNode.put(node, newNode);   
     newNode.next = cc(node.next); 

     //now assign the random pointer 
     RandomListNode newRandom = null; 
     if(node.random != null) 
     { 
      newRandom = createdNode.get(node.random); 
     } 
     newNode.random = newRandom; 

     return newNode;  
    } 
} 

這裏是使用HashMap的(也是JAVA)的解決方案:

public class Solution{ 

    public RandomListNode copyRandomList(RandomListNode head) { 
     if(head == null) return null; 
     java.util.HashMap<RandomListNode, RandomListNode> map = new java.util.HashMap<RandomListNode, RandomListNode>(); 
     RandomListNode copiedHead = new RandomListNode(head.label); 
     map.put(head, copiedHead); 

     for(RandomListNode cur = head.next, cpLst = copiedHead; cur != null; cur = cur.next, cpLst = cpLst.next){ 
      cpLst.next = new RandomListNode(cur.label); 
      map.put(cur, cpLst.next); 
     } 
     for(RandomListNode cur = head, cpCur = copiedHead; cur != null; cur = cur.next, cpCur = cpCur.next) 
      cpCur.random = cur.random == null ? null : map.get(cur.random); 
     return copiedHead; 
    } 
} 

無只讀需求的另一種方法是可以here.

0
  1. 開始從頭節點和一個
  2. 創建節點的副本之一當您創建一個副本,使哈希映射原始節點的進入和複製節點作爲關鍵,價值。
  3. 當我們逐個複製元素時創建一個新列表,所以我們得到了每個節點的下一個指針值。 4.然後用新列表再次遍歷原始列表以複製隨機指針。我們可以在哈希映射中獲得各個節點的隨機指針。

有關詳細說明,請訪問:http://www.dscoding.com/2016/10/copy-linked-list-with-random-pointer.html

相關問題