加载中...

[leetcode]第 2 天 链表(简单)

06. 从尾到头打印链表

思路

说到从尾到头,很容易想到可以用到栈的方式进行处理,那么问题就转化成了如何用辅助栈完成打印链表。可以从链表的头节点开始,依次将每个节点压入栈内,然后依次弹出栈内的元素并存储到数组中。使用到LinkedList的addLast()和removeLast()。

在题目里有一个ListNode对象,ListNode是做什么用的?

public class ListNode{
    int val;
    ListNode next;        //链表指向的下一个值的指针
    ListNode(int x){val = x;}   //这个方式赋值
}
class Solution {
    public int[] reversePrint(ListNode head) {
        LinkedList<Integer> stack = new LinkedList<Integer>();
        while(head != null){
            stack.addLast(head.val);
            head = head.next;
        }
        int[] a = new int[stack.size()];
        for(int i = 0; i < a.length; i++){
            a[i] = stack.removeLast();
        }
        return a;
    }
}

24. 反转链表

思路

一看到反转就想用栈,但是实际上这道题的思路不是这样的。
反转链表的思路是更改指针的方向,流程是:

  1. 保存下一节点
  2. 修改指针方向
  3. 保存当前节点
  4. 处理下一节点
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode cur = head, pre = null;
        while(cur != null) {
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
}

35. 复杂链表的复制

思路

看不懂的题目。。。
官方给出的方法有两种,一种是利用哈希表,一种是利用节点拆分。
如果是普通链表,就能按照遍历的顺序创建链表节点,由于随机指针的存在,拷贝时随机指针指向的节点可能还未被创建。
思路一是让每个节点的拷贝操作相互独立。就是先拷贝当前节点,再拷贝当前节点的后继节点和当前节点随机指针指向的节点,这两个节点还不存在就去拷贝,因此需要用到递归。
为了避免重复创建,可以用到HashMap存储节点创建情况。如果节点为空,则返回null。

class Solution{
  Map<Node, Node> nodeMap = new HashMap<Node, Node>();
  public Node copyRandomList(Node head){
    // 节点为空
    if(head == null){
      return null;
    }  
    // 如果节点未被创建
    if(!nodeMap.containsKey(head)){
      Node headNew = new Node(head.val);
      // 存map
      nodeMap.put(head, headNew);
      // 创建next节点
      headNew.next = copyRandomList(head.next);
      // 创建random节点
      headNew.random = copyRandomList(head.random);
    }
    return nodeMap.get(head);
  }
}

第二种思路是迭代+节点拆分,就是说将每一个节点拆成两个相连的节点,即A->B->C->D拆成A->A'->B->B'->C->C'。
对于原节点,后继节点为拷贝节点。
对于拷贝节点,随机指针指向原节点随机指针指向的节点的后继节点。(S'.random = S.random.next)

class Solution {
    public Node copyRandomList(Node head) {
        if (head == null) {
            return null;
        }
        // 复制链表节点,插入原节点后方
        Node cur = head;
        while(cur != null){
          Node next = cur.next;// 保存下一节点
          cur.next = new Node(cur.val);// new一个新节点
          cur.next.next = next;
          cur = next;// 向右移动
        }
        
        // 复制随机节点
        cur = head;
        while(cur != null){
          Node curNew = cur.next;// 保存下一节点
          curNew.random = cur.random == null? null : cur.random.next;
          cur = cur.next.next;
        }
        
        // 拆分
        Node headNew = head.next;
        cur = head;
        Node curNew = head.next;
        while(cur != null){
          cur.next = cur.next.next;
          cur = cur.next;
          curNew.next = cur == null? null : cur.next;
          curNew = curNew.next;
        }
        return headNew;
    }
}
posted @ 2022-12-19 17:48  Vincy9501  阅读(11)  评论(0编辑  收藏  举报