我需要用下一個和隨機指針複製一個鏈表。下一個指針和通常一樣指向鏈表中的下一個元素,隨機指針可能指向任何其他節點,甚至指向其自身。 如果我不允許在任何時候修改給定的列表,那麼如何完成這項工作,只列出閱讀權限。用下一個和隨機指針複製一個鏈表,在列表中只給出讀取權限
回答
最簡單的解決辦法是這樣的......
您遍歷原來的鏈表,創建另一個鏈表,其節點是一樣的,在最初的名單,在適當的next
指針,指向新列表的相應節點。您現在保留random
指針。
在遍歷列表時,您還將舊列表的節點地址/指針和新列表的節點地址/指針放到associative array
(AKA映射,散列表等)中,其中舊列表的節點地址/指針是key
,新列表的節點地址/指針是value
。
然後就遍歷新的列表以及與所述value
從對應於key
等於random
指針關聯數組的每個節點替換random
指針。
散列表可以用作關聯數組來實現與原始列表中元素數量成比例的時間和內存成本。
時間&該解決方案的空間複雜度分別爲O(n)。
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;
}
歡迎來到Stack Overflow。你可能想要添加一些關於你的答案爲什麼和如何工作的解釋。 (無論是文本還是代碼註釋)。所以OP可以從中學習。 – Oren 2013-03-30 21:06:34
優雅溶液(線性時間,常數空間):
創建節點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.
原始列表爲只讀的限制條件如何? – 2013-09-18 04:14:50
@AlexeyFrunze哦,是的,那麼它不會工作。沒有看到這個限制... – Max 2013-10-14 07:30:21
#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;
}
這段代碼是非常複雜的,沒有對這段代碼的評論是沒有道理的。請留下一些關於此代碼如何工作的意見或解釋,以及如何證明您爲此做出的設計選擇。 – rayryeng 2014-08-30 15:40:00
這裏採取的是遞歸的解決方案(在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.
- 開始從頭節點和一個
- 創建節點的副本之一當您創建一個副本,使哈希映射原始節點的進入和複製節點作爲關鍵,價值。
- 當我們逐個複製元素時創建一個新列表,所以我們得到了每個節點的下一個指針值。 4.然後用新列表再次遍歷原始列表以複製隨機指針。我們可以在哈希映射中獲得各個節點的隨機指針。
有關詳細說明,請訪問:http://www.dscoding.com/2016/10/copy-linked-list-with-random-pointer.html
- 1. 用下一個和隨機指針克隆一個鏈表
- 2. 只使用一個頭指針構造一個隊列鏈表
- 3. 複製鏈接列表,每個節點都有一個變量,它隨機指向另一個節點列表
- 4. 鏈接列表,但每個「下一個」指針指向下一個節點的「下一個」指針
- 5. 如何取一個值,在指針和複製到另一個指針
- 6. 用隨機指針克隆鏈表C++
- 7. C++在鏈接列表設置下一個節點指針
- 8. 隨機從一個列表
- 9. 傳遞一個指針鏈表在C++
- 10. CSS:懸停下拉列表。只需要一個指針
- 11. 如何隨機選取列表中的下一個元素?
- 12. 從一個表複製隨機行到另一個
- 13. 複製一個鏈表
- 14. 生成一個隨機數得到一個隨機列表項
- 15. 生成只使用一個隨機列表中選擇
- 16. 如何使一個鏈接:在C鏈表和指針
- 17. 鏈接列表中的唯一指針
- 18. 複製鏈接列表到另一個鏈接列表
- 19. 限制一個表只有一行
- 20. 只是在列表中沒有選擇的情況下從列表中僞隨機選取一個元素
- 21. 從加權列表中選擇一個隨機項目
- 22. 函數,鏈表。複製一個鏈表到另一個
- 23. 複製一個列表來創建一個列表中,列出了
- 24. 在一個請求中獲取讀取和發佈權限
- 25. 鏈接列表中「下一個」指針的慣用生存期是多少?
- 26. 在sqlite3中:將列從一個表複製到另一個表
- 27. 返回一個只讀雙指針
- 28. 給出一個列表的列表
- 29. 從C++中的int指針返回一個只讀指針
- 30. SQL Server從一個表複製隨機數據到另一個表
要麼我失去了一些東西,或者你的問題的描述是失去了一些東西。當然,如果你已經讀取了原始列表和下一個指針,你只需從列表頭開始,複製該節點並按照下一個指針 - 完成? – us2012 2013-03-06 06:42:12
@ us2012我認爲您應該正確初始化這些「隨機」指針,以便它們指向新列表的節點而不是原始列表的節點。所以,這不是一個完整的節點副本,您需要在每個節點中更改兩個指針。 – 2013-03-06 06:47:40
@Alexey啊!是的,這更有意義。 – us2012 2013-03-06 06:49:53