力扣原题,链表面试题之复制带随机指针的链表

简介: 力扣原题,链表面试题之复制带随机指针的链表

一种特殊的单链表节点类型描述如下:

public static class Node{
    public int value;
    public Node next;
    public Node rand;
    public Node(int v) {
      value=v;
    }
  }

rand指针是单链表节点结构中新增的指针,rand可能指向链表中的任意一个节点,也可能指向null。给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表的复制,并返回复制的新链表的头节点。要求:时间复杂度O(N),额外空间复杂度O(1),注意,无环是指next方向上是无环的!!!

方法一(笔试用,最简单):在next方向上正常遍历一遍链表,遍历过程种将每个结点克隆存入HashMap<Node,Node>,表中的key是老结点,value是克隆的结点。就是人为构造一种对应关系,之后再遍历一遍链表,便可实现,具体看下面代码。但是这种方法在空间复杂度上没有做到O(1)

方法二(面试用):额外空间复杂度O(1),具体看代码

package com.harrison.class06;
import java.util.HashMap;
public class Code04_CopyListWithRandom {
  public static class Node {
    public int value;
    public Node next;
    public Node rand;
    public Node(int v) {
      value = v;
    }
  }
  public static Node copyRandomList1(Node head) {
    HashMap<Node, Node> map = new HashMap<Node, Node>();
    Node cur = head;
    while (cur != null) {
      map.put(cur, new Node(cur.value));
      cur = cur.next;
    }
    cur = head;
    while (cur != null) {
      // cur (key)老结点 map.get(cur) (value)新结点
      map.get(cur).next = map.get(cur.next);
      map.get(cur).rand = map.get(cur.rand);
      cur = cur.next;
    }
    return map.get(head);
  }
  public static Node copyRandomList2(Node head) {
    if (head == null) {
      return null;
    }
    // 1 -> 2 -> 3 -> null
    // 1 -> 1' -> 2 -> 2' -> 3 -> 3' -> null
    Node cur = head;// 老结点
    Node next = null;// 老结点的下一个结点
    while (cur != null) {
      next = cur.next;// next记住老结点的下一个结点
      cur.next = new Node(cur.value);// 当前的老结点指向 复制自己的结点
      cur.next.next = next;// 复制的结点指向 next
      cur = next;
    }
    cur = head;
    Node copy = null;// 复制的结点
    // 依次设置 1' 2' 3' 的rand指针
    while (cur != null) {
      next = cur.next.next;// next 记住老结点的下一个结点
      copy = cur.next;// copy 来到(第一个)复制的结点
      // copy结点的rand指针指向 老结点的rand指针指向的结点的next指针
      copy.rand = cur.rand != null ? cur.rand.next : null;
      cur = next;// 当前结点往下跳
    }
    Node res = head.next;// 记住复制后的链表的头结点
    cur = head;
    // next方向上,把新老链表分离,rand方向不要动
    while (cur != null) {
      next = cur.next.next;// next 记住老结点的下一个结点
      copy = cur.next;// copy 来到(第一个)复制的结点
      // copy结点的next指针指向 下一个老结点的next指针
      copy.next = next != null ? next.next: null;
      cur = next;// 当前结点往下跳
    }
    return res;
  }
  public static void printLinkedList(Node node) {
    System.out.print("Linked List:");
    while (node != null) {
      System.out.print(node.value + " ");
      node = node.next;
    }
    System.out.println();
  }
  public static void main(String[] args) {
    Node head1 = new Node(7);
    head1.next = new Node(9);
    head1.next.next = new Node(1);
    head1.next.next.next = new Node(8);
    head1.next.next.next.next = new Node(5);
    head1.next.next.next.next.next = new Node(2);
    head1.next.next.next.next.next.next = new Node(5);
    printLinkedList(head1);
    //head1=copyRandomList1(head1);
    head1 = copyRandomList2(head1);
    printLinkedList(head1);
  }
}
相关文章
|
1天前
|
Java
【LeetCode力扣】面试题 17.14. 最小K个数(top-k问题)
【LeetCode力扣】面试题 17.14. 最小K个数(top-k问题)
10 1
|
1天前
|
索引
每日一题:力扣328. 奇偶链表
每日一题:力扣328. 奇偶链表
13 4
|
1天前
|
算法
【刷题】 leetcode 面试题 08.05.递归乘法
递归算法是一种在计算机科学和数学中广泛应用的解决问题的方法,其基本思想是利用问题的自我相似性,即将一个大问题分解为一个或多个相同或相似的小问题来解决。递归算法的核心在于函数(或过程)能够直接或间接地调用自身来求解问题的不同部分,直到达到基本情况(也称为基础案例或终止条件),这时可以直接得出答案而不必再进行递归调用。
25 4
【刷题】 leetcode 面试题 08.05.递归乘法
|
1天前
|
存储 算法 安全
【刷题】 leetcode 面试题 01.06 字符串压缩
来看效果: 非常好!!!过啦!!!
25 5
【刷题】 leetcode 面试题 01.06 字符串压缩
|
1天前
leetcode代码记录(移除链表元素
leetcode代码记录(移除链表元素
10 0
|
1天前
|
存储 Java 编译器
链表面试题的总结和思路分享
链表面试题的总结和思路分享
【每日一题】LeetCode——反转链表
【每日一题】LeetCode——反转链表
【每日一题】LeetCode——链表的中间结点
【每日一题】LeetCode——链表的中间结点
|
1天前
|
C++
[leetcode 链表] 反转链表 vs 链表相交
[leetcode 链表] 反转链表 vs 链表相交
|
1天前
【力扣】148. 排序链表
【力扣】148. 排序链表

热门文章

最新文章