leetcode刷题记录——链表

304 阅读3分钟

javascript刷题顺序按照[Leetcode分类顺序表](挂了。。现在就哪里不会刷哪里)(cspiration.com/leetcodeCla…) 👑->VIP题目

链表

面试题 02.03. 删除中间节点

这题要注意的是和传统的链表删除节点有丢丢不一样,因为传入的node是要删除的节点到结尾的这段链表,当前node的pre节点未知,所以这里是先把后一个节点的val赋值到当前节点上,然后再用传统方法删掉当前节点的next节点

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} node
 * @return {void} Do not return anything, modify node in-place instead.
 */
var deleteNode = function(node) {
    node.val = node.next.val;
    node.next = node.next.next;
};

剑指 Offer II 023. 两个链表的第一个重合节点

定义两个指针分别指向A和B,然后遍历链表,当遍历完当前链表后,两个指针交换链表继续遍历,如果两个指针指向同一个节点,则返回这个节点(即第一个重合节点)

这里要注意的地方是无论有没有重合点,两边指针走过(m+n)后就停止。

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getIntersectionNode = function(headA, headB) {
    let p = headA;
    let q = headB;
    while(p || q){
        if (p===null) {
            p = headB;
        }
        if (q===null) {
            q = headA;
        }
        if (p === q) {
            return p
        } else {
            p = p.next;
            q = q.next;
        }
        
    }
    return null
    

};

剑指 Offer 06. 从尾到头打印链表

因为直接打印数组,用unshift可能更简洁(虽然核心思想是利用栈的FILO特性

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {number[]}
 */
var reversePrint = function(head) {
    let arr = []
    let curr = head
    while(curr){
        arr.unshift(curr.val)
        curr = curr.next
    }
    return arr     
};

剑指 Offer 24. 反转链表

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    let prev = null
    let curr = head
    
    while(curr){
        const temp = curr.next;
        curr.next = prev
        prev = curr
        curr = temp
    }
    return prev
    
};

剑指 Offer 35. 复杂链表的复制

  • 方法一:用空间换时间,时间复杂度O(n) 空间复杂度O(n)
    /**
     * // Definition for a Node.
     * function Node(val, next, random) {
     *    this.val = val;
     *    this.next = next;
     *    this.random = random;
     * };
     */
    
    /**
     * @param {Node} head
     * @return {Node}
     */
    var copyRandomList = function(head) {
        if(!head) return head //如果是空链表则直接返回
        let curr = head;
        const map = new Map();
        // 先把链表全都存到map中
        while(curr){
            map.set(curr,new Node(curr.val));
            curr = curr.next;
        }
        curr = head;
        while(curr){
            // Map中get不存在的key,返回值是undefined
            map.get(curr).next = map.get(curr.next) === undefined ? null :  map.get(curr.next);
            map.get(curr).random = map.get(curr.random);
            curr = curr.next;
        }
        return map.get(head)
    };
    
  • 方法二:时间复杂度O(n) 空间复杂度O(1)
    /**
       * // Definition for a Node.
       * function Node(val, next, random) {
       *    this.val = val;
       *    this.next = next;
       *    this.random = random;
       * };
       */
    
      /**
       * @param {Node} head
       * @return {Node}
       */
      var copyRandomList = function(head) {
          if(!head) return head;
          // 第一步根据原始链表的每个节点N创建对应的N',并把N'链接在N后面
          let curr = head;
          while(curr){   
              curr.next = new Node(curr.val,curr.next);
              curr = curr.next.next;
          }
          // 第二步设置复制出来的节点的random。假设原始链表上N的random指向节点S,那么其对应复制出来的N'是N的next指向的节点,S'同样也是S的next指向的节点
          curr = head;
          while(curr){
              if(curr.random !== null){
                  curr.next.random = curr.random.next;
              }
              curr = curr.next.next;
          }
          // 第三步把这个长链表拆分成两个链表,最后返回复制链表的头节点
          curr = head.next
          let dupl = curr;
          let prev = head;
          while(prev.next && curr.next){
              prev.next = prev.next.next;
              curr.next = curr.next.next;
              prev = prev.next;
              curr = curr.next;
          }
          prev.next = null;
          // 返回新链表头节点
          return dupl
    
      };