日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[剑指offer]面试题第[35]题[Leetcode][第138题][JAVA][复杂链表的复制][暴力][HashMap][复制链表]

發布時間:2023/12/10 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [剑指offer]面试题第[35]题[Leetcode][第138题][JAVA][复杂链表的复制][暴力][HashMap][复制链表] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【問題描述】[中等]

【解答思路】

1. 暴力 直接復制

將鏈表從頭節點一個一個復制下去,
在根據記錄的總長度num,遍歷原來的每個節點的random到尾節點個數count,然后順序遍歷找到新鏈表的該指針在num-count上 。
時間復雜度:O(N^2) 空間復雜度:O(N)

class Solution {public Node copyRandomList(Node head) {if(head==null) return head;Node newHead=new Node(head.val);Node keep=newHead;Node node=head.next;int num=1;//記錄節點數while(node!=null){keep.next=new Node(node.val);node=node.next;keep=keep.next;num++;}keep.next=null;Node newn=newHead;Node oldn=head;//n r 定位randomNode n;Node r;int count;while (oldn!=null){n= oldn.random;//進行循環找到酒鏈表random指向的位置nr=newHead;count=0;//計算出舊鏈表n距離尾節點個數while (n!=null){n=n.next;count++;}//計算舊的random在鏈表中的位置 利用新舊鏈表新舊位置相同的原理for(int res=num-count;res>0;res--){r=r.next;}newn.random=r;//遍歷新舊鏈表oldn=oldn.next;newn=newn.next;}return newHead;} }作者:zhao-1z 鏈接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/javaliang-chong-xie-fa-by-zhao-1z/
2. HashMap O(N)空間


**時間復雜度:O(N) 空間復雜度:O(N) **

/* // Definition for a Node. class Node {public int val;public Node next;public Node random;public Node() {}public Node(int _val,Node _next,Node _random) {val = _val;next = _next;random = _random;} }; */ public class Solution {// Visited dictionary to hold old node reference as "key" and new node reference as the "value"HashMap<Node, Node> visited = new HashMap<Node, Node>();public Node getClonedNode(Node node) {// If the node exists thenif (node != null) {// Check if the node is in the visited dictionaryif (this.visited.containsKey(node)) {// If its in the visited dictionary then return the new node reference from the dictionaryreturn this.visited.get(node);} else {// Otherwise create a new node, add to the dictionary and return itthis.visited.put(node, new Node(node.val, null, null));return this.visited.get(node);}}return null;}public Node copyRandomList(Node head) {if (head == null) {return null;}Node oldNode = head;// Creating the new head node.Node newNode = new Node(oldNode.val);this.visited.put(oldNode, newNode);// Iterate on the linked list until all nodes are cloned.while (oldNode != null) {// Get the clones of the nodes referenced by random and next pointers.newNode.random = this.getClonedNode(oldNode.random);newNode.next = this.getClonedNode(oldNode.next);// Move one step ahead in the linked list.oldNode = oldNode.next;newNode = newNode.next;}return this.visited.get(head);} }作者:LeetCode 鏈接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/fu-zhi-dai-sui-ji-zhi-zhen-de-lian-biao-by-leetcod/
3. HashMap O(N)空間

遍歷第一遍鏈表,我們不考慮鏈表之間的相互關系,僅僅生成所有節點,然后把它存到 HashMap 中,h(val) 作為 key,Node 作為 value。

遍歷第二遍鏈表,將之前生成的節點取出來,更新它們的 next 和 random 指針。

時間復雜度:O(N) 空間復雜度:O(N)

public Node copyRandomList(Node head) {if (head == null) {return null;}HashMap<Node, Node> map = new HashMap<>();Node h = head;while (h != null) {Node t = new Node(h.val); map.put(h, t);h = h.next;}h = head;while (h != null) {if (h.next != null) {map.get(h).next = map.get(h.next);}if (h.random != null) {map.get(h).random = map.get(h.random);}h = h.next;}return map.get(head); }作者:windliang 鏈接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-32/
4. HashMap O(N)空間

只遍歷一次鏈表。
核心思想就是延遲更新它的 next。

1 -> 2 -> 3
用 cur 指向已經生成的節點的末尾
1 -> 2
^
c
然后將 3 構造完成
最后將 2 的 next 指向 3
1 -> 2 -> 3
^
c
期間已經生成的節點存到 HashMap 中,第二次遇到的時候直接從 HashMap 中拿

時間復雜度:O(N) 空間復雜度:O(N)

public Node copyRandomList(Node head) {if (head == null) {return null;}HashMap<Node, Node> map = new HashMap<>();Node h = head;Node cur = new Node(-1); //空結點,dummy 節點,為了方便頭結點計算while (h != null) {//判斷當前節點是否已經產生過if (!map.containsKey(h)) {Node t = new Node(h.val);map.put(h, t);}//得到當前節點去更新它的 random 指針Node next = map.get(h);if (h.random != null) {//判斷當前節點是否已經產生過if (!map.containsKey(h.random)) {next.random = new Node(h.random.val);map.put(h.random, next.random);} else {next.random = map.get(h.random);}}//將當前生成的節點接到 cur 的后邊cur.next = next;cur = cur.next;h = h.next;}return map.get(head); }
5. O(1)空間 (用原鏈表的 next 域保存新生成的節點)

主要解決的問題就是我們生成節點以后,當更新它的 random 的時候,怎么找到之前生成的節點,前兩種解法用了 HashMap 全部存起來,這里的話可以利用原來的鏈表的指針域。

主要需要三步。

  • 生成所有的節點,并且分別插入到原有節點的后邊
  • 更新插入節點的 random
  • 將新舊節點分離開來

  • 時間復雜度:O(N) 空間復雜度:O(1)

    public Node copyRandomList(Node head) {if (head == null) {return null;}Node l1 = head;Node l2 = null;//生成所有的節點,并且分別插入到原有節點的后邊while (l1 != null) {l2 = new Node(l1.val);l2.next = l1.next;l1.next = l2;l1 = l1.next.next;}//更新插入節點的 randoml1 = head;while (l1 != null) {if (l1.random != null) {l1.next.random = l1.random.next;}l1 = l1.next.next;}l1 = head;Node l2_head = l1.next;//將新舊節點分離開來while (l1 != null) {l2 = l1.next;l1.next = l2.next;if (l2.next != null) {l2.next = l2.next.next;}l1 = l1.next;}return l2_head; } /* // Definition for a Node. class Node {public int val;public Node next;public Node random;public Node() {}public Node(int _val,Node _next,Node _random) {val = _val;next = _next;random = _random;} }; */ public class Solution {public Node copyRandomList(Node head) {if (head == null) {return null;}// Creating a new weaved list of original and copied nodes.Node ptr = head;while (ptr != null) {// Cloned nodeNode newNode = new Node(ptr.val);// Inserting the cloned node just next to the original node.// If A->B->C is the original linked list,// Linked list after weaving cloned nodes would be A->A'->B->B'->C->C'newNode.next = ptr.next;ptr.next = newNode;ptr = newNode.next;}ptr = head;// Now link the random pointers of the new nodes created.// Iterate the newly created list and use the original nodes' random pointers,// to assign references to random pointers for cloned nodes.while (ptr != null) {ptr.next.random = (ptr.random != null) ? ptr.random.next : null;ptr = ptr.next.next;}// Unweave the linked list to get back the original linked list and the cloned list.// i.e. A->A'->B->B'->C->C' would be broken to A->B->C and A'->B'->C'Node ptr_old_list = head; // A->B->CNode ptr_new_list = head.next; // A'->B'->C'Node head_old = head.next;while (ptr_old_list != null) {ptr_old_list.next = ptr_old_list.next.next;ptr_new_list.next = (ptr_new_list.next != null) ? ptr_new_list.next.next : null;ptr_old_list = ptr_old_list.next;ptr_new_list = ptr_new_list.next;}return head_old;} }
    6. O(1)空間 (用原鏈表的 random域保存新生成的節點)

    可以利用原鏈表的 random 域把新生成的節點保存起來。
    主要還是三個步驟。

  • 生成所有的節點,將它們保存到原鏈表的 random 域,同時利用新生成的節點的 next 域保存原鏈表的 random。
  • 更新新生成節點的 random 指針。
  • 恢復原鏈表的 random 指針,同時更新新生成節點的 next 指針。
  • 時間復雜度:O(N) 空間復雜度:O(1)

    public Node copyRandomList(Node head) {if (head == null) {return null;}Node l1 = head;Node l2 = null;//生成所有的節點,講它們保存到原鏈表的 random 域,//同時利用新生成的節點的 next 域保存原鏈表的 random。while (l1 != null) {l2 = new Node(l1.val);l2.next = l1.random;l1.random = l2;l1 = l1.next;}l1 = head;//更新新生成節點的 random 指針。while (l1 != null) {l2 = l1.random;l2.random = l2.next != null ? l2.next.random : null;l1 = l1.next;}l1 = head;Node l2_head = l1.random;//恢復原鏈表的 random 指針,同時更新新生成節點的 next 指針。while (l1 != null) {l2 = l1.random;l1.random = l2.next;l2.next = l1.next != null ? l1.next.random : null;l1 = l1.next;}return l2_head; }

    【總結】

    1.思路1暴力O(N^2)-> 思路2.3.4 HashMap O(N)->思路5.6 復制鏈表O(1)
    2.鏈表操作的核心思想就是,在改變某一個節點的指針域的時候,一定要把該節點的指針指向的節點用另一個指針保存起來,以免造成丟失。
    3.鏈表 畫圖

    轉載鏈接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-32/
    轉載鏈接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-32/

    總結

    以上是生活随笔為你收集整理的[剑指offer]面试题第[35]题[Leetcode][第138题][JAVA][复杂链表的复制][暴力][HashMap][复制链表]的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。