# leetcode刷题阶段性总结(链表篇)

85 阅读2分钟

项目地址: github.com/AlienGao/le…

2. 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

解题思路

两数相加结果有两种,一种小于10不需要进位,另一种大于等于10需要进位(两数相加后取首位a + b | 0)。设置一个变量(carry)来存储进位,默认为0。某一位的值其实是两个数字对应位置只和与进位相加取余的结果。再遍历个链表,将每一位相加。

var addTwoNumbers = function(l1, l2) {
    let head = null, tail = null;
    let carry = 0;
    while (l1 || l2) {
        let n1 = l1 ? l1.val : 0
        let n2 = l2 ? l2.val : 0
        let sum = n1 + n2 + carry
        if (!head) {
            head = tail = new ListNode(sum % 10)
        } else {
            tail.next = new ListNode(sum % 10)
            tail = tail.next
        }
        carry = sum / 10 | 0
        if (l1) {
            l1 = l1.next
        }
        if (l2) {
            l2 = l2.next
        }
    }
    if (carry > 0) {
        tail.next = new ListNode(carry)
    }
    return head
};

21. 合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

解题思路

假设l1为新链表起始,将当前位与l2当前位比较,若小于l2当前位,l1指针往下走一位,再和l2比较,若大于l2,则l2走一位。

var mergeTwoLists = function(l1, l2) {
   if (!l1) return l2
   if (!l2) return l1
   if (l1.val < l2.val) {
       l1.next = mergeTwoLists(l1.next, l2)
       return l1
   } else {
       l2.next = mergeTwoLists(l2.next, l1)
       return l2
   }
};

141. 环形链表

给定一个链表,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。 如果链表中存在环,则返回 true 。 否则,返回 false 。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

解题思路

使用快慢指针,慢指针每次走一步,快指针每次走两步,若快慢指针相遇,则说明有环。若快指针指向null则遍历结束,表明没有环。

var hasCycle = function(head) {
    if (!head || !head.next) return false
    let slow = head
    let fast = head
    // 快慢指针 若相遇则表明有环
    while(fast.next && fast.next.next) {
        slow = slow.next;
        fast = fast.next.next;
        if (slow === fast) {
            return true
        }
    }
    return false
};

203. 移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:

输入:head = [], val = 1
输出:[]

解题思路

使用迭代,若指针指向的值与整修相等,则指针向后走一位。

var removeElements = function(head, val) {
    if (head === null) {
        return head
    }
    head.next = removeElements(head.next, val)
    return head.val === val ? head.next : head
};

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

输入:head = [1,2]
输出:[2,1]

解题思路

设置一个变量prv用来存储head当前指针的值,并设置head的后一位为prv。相当于head.next -> head,则能实现反转。

var reverseList = function(head) {
    let prv = null
    let cur = head
    while(cur) {
        const next = cur.next
        cur.next = prv
        prv = cur
        cur = next
    }
    return prv
};