LeetCode 题集:链表(二)

本文介绍 LeetCode 题集中,有关链表的问题。

LeetCode 其他有关链表的问题:
LeetCode 题集:链表(一)
LeetCode 题集:链表(三)

2. Add Two Numbers(两数相加)


问题描述

LeetCode 2 问题描述 I
LeetCode 2 问题描述 II

思路与代码


本题的思路较为简单,主要注意两点:

  • 两个链表表上的数字位数可能不同,即链表长度不同
  • 进位的情况,最后还可能有一次额外的进位,如:99 + 999 = 1098

代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        list_res = []

        s, b, c = 0, 0, 0  # sum, current bit, carrying to next bit
        while l1 and l2:
            s = l1.val + l2.val + c
            b, c = s % 10, int(s / 10)
            list_res.append(b)
            l1, l2 = l1.next, l2.next

        while l1:
            s = l1.val + c
            b, c = s % 10, int(s / 10)
            list_res.append(b)
            l1 = l1.next
        while l2:
            s = l2.val + c
            b, c = s % 10, int(s / 10)
            list_res.append(b)
            l2 = l2.next
        while c:  # maybe have an extra carry bit
            list_res.append(c)
            c = 0

        # result ListNode
        i = 0
        head = ListNode(val=list_res[i])
        res = head
        while i + 1 < len(list_res):
            node = ListNode(val=list_res[i + 1])
            head.next = node
            head = node
            i += 1
        head.next = None

        return res

运行效果:
LeetCode 2 运行效果


445. Add Two Numbers II(两数相加 II)


问题描述

LeetCode 445 问题描述 I
LeetCode 445 问题描述 II

思路与代码


本题最直接的思路,是先遍历两个链表得到对应的数字,然后求和,写入结果链表。

代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        # sum up the number
        num_1, num_2 = 0, 0
        while l1:
            num_1 = num_1 * 10 + l1.val
            l1 = l1.next
        while l2:
            num_2 = num_2 * 10 + l2.val
            l2 = l2.next
        num = num_1 + num_2

        str_num = str(num)  # number to string
        dummy = ListNode(val=-1)
        head = dummy
        for c in str_num:  # each digit to node
            node = ListNode(val=int(c))
            head.next = node
            head = head.next

        res = dummy.next

        return res

运行效果:
LeetCode 445 运行效果 1

此外,官方题解给出了一种通过栈来解决本题的思路。

LeetCode 445 官方题解

代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        s1, s2 = [], []
        while l1:
            s1.append(l1.val)
            l1 = l1.next
        while l2:
            s2.append(l2.val)
            l2 = l2.next
        
        ans = None
        carry = 0
        while s1 or s2 or carry != 0:
            a = 0 if not s1 else s1.pop()
            b = 0 if not s2 else s2.pop()
            cur = a + b + carry
            carry = int(cur / 10)
            cur %= 10

            curnode = ListNode(val=cur)
            curnode.next = ans
            ans = curnode
            
        return ans

运行效果:
LeetCode 445 运行效果 2


83. Remove Duplicates from Sorted List(删除排序链表中的重复元素)


问题描述

LeetCode 83 问题描述 I
LeetCode 83 问题描述 II

思路与代码


本体的思路较为简单,由于链表中的数值为有序排列,因此只需考虑每个节点的下一个节点的数值是否与当前节点相等即可。

代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        res = head
        while head:
            while head.next and head.next.val == head.val:
                head.next = head.next.next
            head = head.next

        return res

运行效果:
LeetCode 83 运行效果


82. Remove Duplicates from Sorted List II(删除排序链表中的重复元素 II)


问题描述

LeetCode 82 问题描述 I
LeetCode 82 问题描述 II

思路与代码


本题为前一题的变体,区别在于需要删除所有重复值节点,包括第一次出现的节点。可以使用快慢指针的方法,快指针先行遍历,直到发现非重复值,慢指针再调整 next 指向,如此循环即可,注意处理结尾为重复值的情况。

代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        dummy = ListNode(val=-1, next=head)
        fast, slow = dummy.next, dummy

        # edge case: no nodes
        if not fast:
            return fast

        is_dup = False
        while fast.next:
            fast = fast.next  # keep fast preceding slow
            if slow.next.val != fast.val:
                if is_dup:
                    is_dup = False
                    slow.next = fast
                else:
                    slow = slow.next

            else:
                is_dup = True

        # in case: tail is duplicated
        if is_dup:
            slow.next = None

        res = dummy.next

        return res

运行效果:
LeetCode 82 运行效果

21. Merge Two Sorted Lists(合并两个有序链表)


问题描述

LeetCode 21 问题描述

思路与代码


本题可参考本文第一题(LeetCode 2)的结构,即注意处理链表比较大小后的剩余节点情况。

代码如下:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        dummy = ListNode(val=-1)
        head = dummy
        while l1 and l2:
            if l1.val <= l2.val:
                head.next = l1
                head, l1 = head.next, l1.next
            else:
                head.next = l2
                head, l2 = head.next, l2.next

        while l1:
            head.next = l1
            head, l1 = head.next, l1.next
        while l2:
            head.next = l2
            head, l2 = head.next, l2.next

        res = dummy.next

        return res

运行效果:
LeetCode 21 运行效果


88. Merge Sorted Array(合并两个有序数组)


问题描述

LeetCode 88 问题描述 I
LeetCode 88 问题描述 II

思路与代码


本题与链表无关,只是与前一题相似,都是按大小顺序对两个数组(链表)进行合并,因此代码结构也与前一题相同。

代码如下:

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """

        i, j, k = 0, 0, 0
        nums_tmp = nums1.copy()
        while i < m and j < n:
            if nums_tmp[i] <= nums2[j]:
                nums1[k] = nums_tmp[i]
                i += 1
            else:
                nums1[k] = nums2[j]
                j += 1
            k += 1

        while i < m:  # nums1 remaining
            nums1[k] = nums_tmp[i]
            i += 1
            k += 1
        while j < n:  # nums2 remaining
            nums1[k] = nums2[j]
            j += 1
            k += 1

运行效果:
LeetCode 88 运行效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值