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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

数据结构与算法--复杂链表的复制

發布時間:2023/12/4 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构与算法--复杂链表的复制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

復雜鏈表的復制

  • 題目:實現一個函數complexListNode 復制一個復雜鏈表。在鏈表中,每個節點除了有一個next指針指向下一個節點,還有另外一個before節點,before節點指向鏈表中任意一個節點,或者null節點。
  • 鏈表節點定義使用之前文章 數據結構與算法–鏈表實現以及應用 中鏈表節點的定義,以及鏈表中其他方法實現都沿用以上文章中有詳細的說明。
  • 如下節點定義:
public class ListNode implements Comparable<ListNode> {private Integer value;private ListNode next;private ListNode before; ...... }
  • 如下圖中包含的5個階段的復雜鏈表,圖中實線箭頭表示next指針,虛線表示before指針,簡單畫出如下,我們省略了null指針沒有畫出來:

  • 分析:

    • 方法一:如上鏈表的結構看最簡單的方式先遍歷一次,將節點復制,并且用next 鏈接節點,得到基礎結構
    • 在循環查找每一個節點的before節點,因為此處before節點是隨機指向,可能指向本節點之前的節點,因此每次都需要遍歷一次鏈表來查找對應的節點信息
    • 時間復雜度O(N2)
    • 方法二:為了避免before節點查找的復雜性,先遍歷一次oldList,復制next指針,并且將oldNode,newNode存儲到map中,
    • 第二次遍歷,此時我們已經知道了oldNode~ newNode的對應關系,我們在查找到oldList的before指向的時候,直接從map中獲取到對應newNode,這樣通過O(1) 時間獲取到before的值
    • 此處空間換時間的方法
    • 方法三:換一種思路,能否不用輔助空間情況下來實現O(n)的時間復雜度,
    • 第一次遍歷,直接將訪問到的節點復制新節點,并且插入到訪問到的節點后面,如下圖:
    • 第二次遍歷,設置新建節點的before節點,因為每個新節點A‘都在老節點A的next位置,所以,老節點A 的before C節點的next 就是改節點的新節點C’ 那么新節點A‘ 的before節點就是 C’
    • 第三次遍歷,將奇數項的節點單獨拆分成一個鏈表得到我們復制的鏈表,偶數位項就是老的鏈表
  • 根據如上分析有如下代碼:

/*** 構建復雜鏈表,鏈表next節點指向下一個節點,* before節點指向鏈表中任意節點* */public static ListNode buildComplexListNode(){Random random = new Random();ListNode pHead = new ListNode(random.nextInt(100));ListNode[] nodeArray = new ListNode[20];for (int i = 0; i < 20; i++) {ListNode newNode = new ListNode(random.nextInt(100));nodeArray[i] = newNode;ListNode headNode = pHead;while (headNode.getNext() != null){headNode = headNode.getNext();}headNode.setNext(newNode);}print(pHead);ListNode headNode = pHead;while (headNode.getNext() != null){headNode.setBefore(nodeArray[random.nextInt(nodeArray.length -1)]);headNode = headNode.getNext();}return pHead;}/*** 復制復雜鏈表* 方法一:空間換時間,* 先遍歷一次oldList,復制next指針,并且將oldNode,newNode存儲到map中,* 第二次遍歷同時遍歷oldList,newList,直接通過oldList的before指向的oldListNode從mep中獲取newNode,* O(1)時間獲取到before值* */public static ListNode complexListNode(ListNode pHead){if(pHead == null || pHead.getNext() == null){return pHead;}Map<ListNode, ListNode> oldToNewNode = new HashMap<>();ListNode complexNode = pHead;ListNode newHead = null;ListNode myHeadNode = null;while (complexNode != null){ListNode createNode = new ListNode(complexNode.getValue());oldToNewNode.put(complexNode, createNode);if(newHead == null){newHead = createNode;myHeadNode = newHead;}else {myHeadNode.setNext(createNode);myHeadNode = myHeadNode.getNext();}complexNode = complexNode.getNext();}ListNode beforeComplexNode = pHead;ListNode beforeSetNode = newHead;while (beforeComplexNode.getNext() != null && beforeSetNode.getNext() != null){if(oldToNewNode.containsKey(beforeComplexNode.getBefore())){beforeSetNode.setBefore(oldToNewNode.get(beforeComplexNode.getBefore()));}beforeComplexNode = beforeComplexNode.getNext();beforeSetNode = beforeSetNode.getNext();}return newHead;} /*** 復制復雜鏈表* 方法二:* 第一次遍歷,直接將范問到的節點復制新節點,并且插入到范問到的節點后面* 第二次遍歷,設置新建節點的before節點,因為每個新節點A‘都在老節點A的next位置,所以,老節點的before B節點的next 就是改節點的新節點B’* 那么新節點A‘的before節點就是B’* 第三次遍歷,將奇數項的節點單獨拆分成一個鏈表得到我們復制的鏈表,偶數位項就是老的鏈表*/public static ListNode complexListNode_2(ListNode pHead){if(pHead == null || pHead.getNext() == null){return pHead;}ListNode compleNode = pHead;while (compleNode.getNext() != null){ListNode createNode = new ListNode(compleNode.getValue());createNode.setNext(compleNode.getNext());compleNode.setNext(createNode);compleNode = compleNode.getNext().getNext();}ListNode beforeCompleNode = pHead;while (beforeCompleNode.getNext() != null){if(beforeCompleNode.getBefore() != null){beforeCompleNode.getNext().setBefore(beforeCompleNode.getBefore().getNext());}beforeCompleNode = beforeCompleNode.getNext().getNext();}ListNode fixCompleNode = pHead;ListNode resultHead = null;ListNode resultNode = null;while (fixCompleNode.getNext() != null){if(resultHead == null){resultHead = fixCompleNode.getNext();resultNode = resultHead;}else {resultNode.setNext(fixCompleNode.getNext());resultNode = resultNode.getNext();}fixCompleNode = fixCompleNode.getNext().getNext();}return resultHead;}public static void printListNode(ListNode pHead){ListNode printNode = pHead;while (printNode.getNext() != null){System.out.print("value: " + printNode.getValue());System.out.print(", ");System.out.print("before: " + (printNode.getBefore() != null ? printNode.getBefore().getValue() : ""));System.out.print(", ");System.out.print("next: " + (printNode.getNext() != null ? printNode.getNext().getValue() : ""));printNode = printNode.getNext();System.out.println();}}public static void main(String[] args) {ListNode oldListNode = buildComplexListNode();System.out.println("oldListNode:");printListNode(oldListNode);System.out.println("newListNode:");ListNode mewListNode = complexListNode(oldListNode);printListNode(mewListNode);ListNode newListNode_2 = complexListNode_2(oldListNode);System.out.println("newListNode_2:");printListNode(newListNode_2);}
  • 以上代碼中其他未定義方法都沿用 數據結構與算法–鏈表實現以及應用 中對應的方法。

上一篇:數據結構與算法-- 二叉樹中和為某一值的路徑
下一篇:數據結構與算法–二叉查找樹轉順序排列雙向鏈表

總結

以上是生活随笔為你收集整理的数据结构与算法--复杂链表的复制的全部內容,希望文章能夠幫你解決所遇到的問題。

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