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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【三次优化】剑指 Offer 35. 复杂链表的复制

發布時間:2024/2/28 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【三次优化】剑指 Offer 35. 复杂链表的复制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

立志用最少代碼做最高效的表達


請實現 copyRandomList 函數,復制一個復雜鏈表。在復雜鏈表中,每個節點除了有一個 next 指針指向下一個節點,還有一個 random 指針指向鏈表中的任意節點或者 null。

示例 1:
輸入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
輸出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

示例 2:
輸入:head = [[1,1],[2,1]]
輸出:[[1,1],[2,1]]

示例 3:
輸入:head = [[3,null],[3,0],[3,null]]
輸出:[[3,null],[3,0],[3,null]]

示例 4:
輸入:head = []
輸出:[]
解釋:給定的鏈表為空(空指針),因此返回 null。

提示:
-10000 <= Node.val <= 10000
Node.random 為空(null)或指向鏈表中的節點。
節點數目不超過 1000 。


思路一:HashMap

思路:以map將新節點和舊節點映射起來,進而建立鏈表。
步驟
1、完成以next指針為串聯的鏈表的建立,并建立HashMap映射
2、完成random的鏈表建設
缺點:冗余

class Solution {public Node copyRandomList(Node head) {/**1、根據next完成鏈表的復制,同時建立hash表映射2、根據hash表的映射進行random的指向*/if(head == null) return null; //頭結點為空的情況Map<Node, Node> map = new HashMap<>(); // 建立Map映射,映射原節點和被復制的節點Node copyListHead = new Node(head.val); // 復制鏈表的頭結點map.put(head, copyListHead); // 建立頭結點間的映射Node oldTmpList1 = head.next; // 原鏈表的臨時遍歷節點Node copyTmpList1 = copyListHead; // 復制鏈表的臨時遍歷節點1// 1、完成next的復制while(oldTmpList1 != null) {Node newTmpList1 = new Node(oldTmpList1.val); // 賦值鏈表的臨時遍歷節點2(因為建表需要兩個節點)map.put(oldTmpList1, newTmpList1); // 建立映射copyTmpList1.next = newTmpList1; // 建表過程copyTmpList1 = newTmpList1;oldTmpList1 = oldTmpList1.next;}// 2、完成random的復制Node oldTmpList2 = head;Node newTmpList2 = copyListHead; // 復制鏈表的臨時遍歷節點1while(oldTmpList2 != null) {if(oldTmpList2.random != null) {newTmpList2.random = map.get(oldTmpList2.random);}oldTmpList2 = oldTmpList2.next;newTmpList2 = newTmpList2.next;}return copyListHead;} }

思路2:對思路1的優化

拆分成兩步:
1、將新舊節點映射起來
2、進行next和random的鏈表建立
時間復雜度:O(n) 、 空間復雜度:O(n)

class Solution {public Node copyRandomList(Node head) {if(head == null) return null; //頭結點為空的情況Map<Node, Node>map = new HashMap<>(); // 建立Map映射,映射原節點和被復制的節點Node copyListHead = new Node(head.val); // 復制鏈表的頭結點// 1、進行Map映射for(Node tmp = head; tmp != null; tmp = tmp.next) {if(tmp == head) map.put(head, copyListHead); // 頭結點單獨判斷else map.put(tmp, new Node(tmp.val)); // 建立映射}// 2、完成next的復制和random的復制for(Node tmp = head; tmp != null; tmp = tmp.next) {map.get(tmp).next = map.get(tmp.next);map.get(tmp).random = map.get(tmp.random);}return copyListHead;} }

代碼3:原地復制

思路:在原鏈表的每個節點后都構建一個新節點,將原來形如A->B->C的鏈表改為A->A'->B->B'->C->C',然后拆分兩鏈表即可。

步驟
1、復制各個節點,構建拼接鏈表
2、構建各個新節點的random指針
3、拆分成兩個鏈表

注意:本題的題意是深拷貝,即不能更改原鏈表。

class Solution {public Node copyRandomList(Node head) {if(head == null) return null;Node cur = head;// 1. 復制各節點,并構建拼接鏈表while(cur != null) {Node tmp = new Node(cur.val);tmp.next = cur.next;cur.next = tmp;cur = tmp.next;}// 2. 構建各新節點的 random 指向cur = head;while(cur != null) {if(cur.random != null)cur.next.random = cur.random.next;cur = cur.next.next;}// 3. 拆分兩鏈表cur = head.next;Node pre = head, res = head.next;while(cur.next != null) {pre.next = pre.next.next;cur.next = cur.next.next;pre = pre.next;cur = cur.next;}pre.next = null; // 單獨處理原鏈表尾節點return res; // 返回新鏈表頭節點} }

總結

以上是生活随笔為你收集整理的【三次优化】剑指 Offer 35. 复杂链表的复制的全部內容,希望文章能夠幫你解決所遇到的問題。

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