Leetcode日练笔记33 [linked list专题] #21 #2 Merge Two Sorted Lists & Add Two Numbers

这篇博客详细介绍了LeetCode题目#21 'Merge Two Sorted Lists'和#2 'Add Two Numbers'的解题思路。对于归并排序链表,博主探讨了迭代和递归两种方法,重点讲解了递归解法的实现。而对于加法运算,博主首先采用迭代方式,然后尝试使用递归,分析了递归解法的优势和简洁性,并分享了优化技巧。
摘要由CSDN通过智能技术生成

#21 Merge Two Sorted Lists

You are given the heads of two sorted linked lists list1 and list2.

Merge the two lists in a one sorted list. The list should be made by splicing together the nodes of the first two lists.

Return the head of the merged linked list.

解题思路:

分两种,一个是iterative的,另外一个是recursive的。后者的time 和 space complexity都是O(m+n)。前者time complexity是O(m+n),space complexity是O(1)【这里暂时不明白】。

iterative的方法是先排除两个list没有节点的情况,然后比较两个list排头的val大小,小的放入新的list中,然后继续比较后续的节点,直到其中一个list没有节点为止,就把另外一个list剩下的节点接在新list的后面。新的list操作时需要两个pointers,一个是记录整个list,head。另外一个是接最小值用的,tail。

# rule out the possibility of either list1 or list2 is None
        if not list1:
            if not list2:
                return None
            else:
                return list2
        else:
            if not list2:
                return list1
        
        # create a new linked list
        head = ListNode(0)
        
        # attach the smallest nodes from two linked lists to the new one
        while list1 and list2:
            if list1.val <= list2.val:
                # the first node attached to head
                if not head.next:
                    head.next = list1
                    tail = head.next
                # not the first node
                else:
                    tail.next = list1
                    tail = tail.next
                list1 = list1.next
            else:
                if not head.next:
                    head.next = list2
                    tail = head.next
                else:
                    tail.next = list2
                    tail = tail.next
                list2 = list2.next
            
        # when either of the linked list reached to the end
        if not list1:
            tail.next = list2
        else:
            tail.next = list1
        
        return head.next

recursive的办法就是假设前面的点都接好了,后面的下一循环也会处理好。只聚焦当前的节点。当前两个list的的节点比较完大小之后,小值当头,头的下一个设置为剩下的节点再进入下一个循环的结果。

# 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, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        if not list1: return list2
        if not list2: return list1
        
        if list1.val <= list2.val:
            head = list1
            list1.next = self.mergeTwoLists(list1.next, list2)
        else:
            head = list2
            list2.next = self.mergeTwoLists(list2.next, list1)
            
        return head

recursive就理解起来很难,写起来会简洁很多。相当于iterative里的while循环终止条件要放在最前面考虑,套用回自己记得用self.

#2 Add two numbers

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

解题思路:

1.先创建新list的head,连接新节点的tail,以及记录逢十进一的add。

2.然后进入两节点相加的循环处理,只要任一list有节点在,都需要做相加的操作。如果其中一个list已经为None了,那设置其值为0。得到的和,取除以10的余数生成新的节点,连接到新list的tail上。然后list的节点、tail往后移。直到所有节点相加完。

3.最后看add是否为1,是的话就创建值为1的新节点,连接给tail,最后输出head。

# 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: Optional[ListNode], l2: Optional[ListNode], add = 0) -> Optional[ListNode]:
        head = ListNode()
        tail = head
        
        while l1 or l2:
            l1val = 0 if not l1 else l1.val
            l2val = 0 if not l2 else l2.val
            sum = l1val + l2val + add
            val = sum % 10
            tail.next = ListNode(val)
            add = 1 if sum > 9 else 0
            l1 = l1.next if l1 else l1
            l2 = l2.next if l2 else l2
            tail = tail.next
            
        if add == 1:
            tail.next = ListNode(1)
            
        return head.next

 本来想用recursive的思路,但写着写着还是变成了iterative。

runtime:

参考了50ms的solution:

 

发现if add == 1: 那里其实可以合并进入while循环里。实际上加值为1的节点那里可以省略。其他基本一样。

还在forum看到可以合并add 与sum的方法:

 创建新节点是val直接是sum%10, 然后add可以改为 sum //= 10。妙喵喵。

recursive的思路

前面还是因为不习惯recursive的思路演算过程,所以还是要强迫自己多练一下。

recursive的思路,参考上一题Merged Two Linked List的思路,先讨论list 1以及list 2都不存在的情况。和iterative的思路正好相反,相当于先思考循环跑完之后,怎么处理。处理步骤从后往前推演。

1.当节点都不在了,而且上一次节点相加之和超过了十的话,那么就还要返回一个新的值为1的节点。如果没有超过十,就什么也不返回。

2.如果只是其中一个list的节点用完了,那么就创建一个ghost值为0,还是继续进行相加的处理操作。

# 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: Optional[ListNode], l2: Optional[ListNode], add = 0) -> Optional[ListNode]:
        if not l1 and not l2:
            if add == 1: 
                return ListNode(1) 
            else:
                return 
        
        if l1:
            l1val = l1.val  
            l1 = l1.next
        else:
            l1val = 0
        if l2:
            l2val = l2.val
            l2 = l2.next
        else:
            l2val = 0
           
        sum = l1val + l2val + add
        val = sum % 10
        head = ListNode(val)
        add = 1 if sum > 9 else 0
        
        head.next = self.addTwoNumbers(l1, l2, add)
        
        return head

runtime:

recursive 居然快那么多。amzg. 

看到更简洁的解法:

 也是和之前看到的iterative的解法一样,把sum和add合并处理了。l2val取值的时候是顺便和l1val相加了。而且用nextSum和两次self.addTwoNumbers,提前处理了逢十进一的情况。tql。真的很难绕过来。再多练吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值