程序员代码面试指南 —— 链表问题(三)

题目:复制含有随机指针节点的链表
描述:有一种链表节点类描述如下:
public class Node {
public int value;
public Node next;
public Node rand;
public Node(int data){
this.value = data;
}
}

Node 类中的value是节点值,next指针和正常单链表中next指针的意义一样,都指向下一个节点,rand指针是Node类中新增的指针,这个指针可能指向链表中的任意一个节点,也可能指向null。
  给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表中所有结构的复制,并返回复制的新链表的头结点。例如链表 1 —> 2 —>3 —> null,假如:1的rand指针指向3,2的rand指针指向null,3的rand指针指向  1,复制后的链表也应该具有这种关系
  
思路:
  方法一:描述对应关系,可以考虑散列表
  1) 从左到右遍历链表,对每个节点都生成对应的副本节点,然后将对对应关系放入哈希map中
步骤:
  1 完成后,原链表没有任何变化,每一个副本节点的next和rand指针都指向null
  2.再从左到右遍历链表,此时就可以设置每一个副本节点的rend和next指针
例如:原链表 1 —>2 —>3 —>null,假设1的rand指针指向3,2的rand指针指向null,3的rand指针指向1.遍历到1节点的时候,可以从map中得到1的副本节点1’ ,1的next指向2 ,所以从map中找到2的副本 2’,令1’->2’,同时指定1’的rand指针指向
  3.经过两次遍历之后,返回散列表中 key = head 的值即可
代码实现:

private static Node copyChain(Node head) {
           HashMap<Node,Node> map = new HashMap();
      Node cur = head;
      while(cur != null){
        map.put(cur,new Node(cur.value));
        cur = cur.next;
      }
      cur = head;
      while (cur != null){
        map.get(cur).next = map.get(cur.next);
        map.get(cur).rand = map.get(cur.rand);
        cur = cur.next;
      }
      return map.get(head);
  }

方法二:用有限的变量去完成该功能
  1) 从左到右遍历链表,把每个节点cur都复制一份copy,然后把copy放在cur和下一个要遍历的节点中间 1—>1’—>2—>2’—>3—>3’
  2)再从左到右遍历链表,在遍历时设置每一个副本节点的rand
  3)步骤2完成之后,节点1,2,3之间的rand没有变化,而节点1’ 2’ 3’之间的rand关系也被正确设置了,只要将其分离即可
代码实现:

private static Node copyChain(Node head) {
    if (head == null) {
      return null;
    }
    Node cur = head;
    Node next = null;
    // 复制节点
    while (cur != null) {
      next = cur.next;
      cur.next = new Node(cur.value);
      cur.next.next = next;
    }
    cur = head;
    Node curCopy = null;
 
    // 设置复制节点的rand指针
    while (cur != null) {
      next = cur.next.next;
      curCopy = cur.next;
      curCopy.rand = cur.rand != null ? cur.rand.next : null;
      cur = next;
    }
    Node res = head.next;
    cur = head;
    
    //拆分
    while (cur != null){
      next = cur.next.next;
      curCopy = cur.next;
      cur.next = next;
      curCopy.next = next != null ? next.next:null;
      cur = next;
    }
    return res;
  }

题目:两个单链表生成相加链表
问题描述:
  假设链表中的每一个节点的值都在0-9之间,那么链表整体就可以代表一个整数,例如9 -> 3 ->7,可以代表937,给定这两种链表的头节点head1和head2,请生成代表两个数相加值的结果链表
思路:
  可以对链表求其逆序链表,求完之后,将两数相加,给定一个是否进位的进位标值sign,即可。
代码实现:

public class AddChain {
  public static void main(String[] args) {
    // init()
    Node head1 = new Node(9);
    Node node1 = new Node(3);
    Node node2 = new Node(7);
 
    Node head2 = new Node(6);
    Node node3 = new Node(3);
 
    head1.next = node1;
    node1.next = node2;
 
    head2.next = node3;
 
    Node reHead1 = ReverNode(head1);
    Node reHead2 = ReverNode(head2);
 
    Node res = add(reHead1, reHead2);
    res = ReverNode(res);
    Node h = res;
    while (h != null) {
      System.out.print(h.value + " ");
      h = h.next;
    }
  }
 
  private static Node add(Node head1, Node head2) {
    Node head = new Node(0);
    Node h = head;
    int ca = 0;
    while (head1 != null && head2 != null) {
      int res = head1.value + head2.value + ca;
      ca = 0;
      if (res > 9) {
        res = res - 10;
        ca++;
      }
      h.next = new Node(res);
      h = h.next;
      head1 = head1.next;
      head2 = head2.next;
    }
    
    while (head1 != null) {
      int res = head1.value + ca;
      ca = 0;
      if (res > 9) {
        res = res - 10;
        ca++;
      }
      h.next = new Node(res);
      h = h.next;
      head1 = head1.next;
    }
 
    while (head2 != null) {
      int res = head2.value + ca;
      ca = 0;
      if (res > 9) {
        res = res - 10;
        ca++;
      }
      h.next = new Node(res);
      h = h.next;
      head2 = head2.next;
    }
 
    if(ca != 0){
        h.next = new Node(ca);
        h = h.next;
    }
    return head.next;
  }
 
  private static Node ReverNode(Node head) {
    Node next = null;
    Node pre = null;
    while (head != null) {
      next = head.next;
      head.next = pre;
      pre = head;
      head = next;
    }
    return pre;
  }
}


猜你喜欢

转载自blog.csdn.net/Kirito19970409/article/details/84068500