21. 合并两个有序链表
背景
这个题目一般用来学习数据结构时练手用。但我们今天只研究递归,按tag刷。
题目链接:https://leetcode.cn/problems/merge-two-sorted-lists/description/
递归解题一般思路
递归程序设计,对新手来说是个难点。
递归的主题思想是:
- 递归是有穷的,即不能无限递归下去。
- 为了达成1,所以递归每次都能缩小问题的规模。
- 因为递归是自己调用自己,所以递归每次的处理都是一样的。
- 为了递归能够退出,我们要设计好递归的退出条件。
所以,递归最重要的就是:
- 我们设计好本层做什么事情,怎么才能缩小规模。
- 我们设计好递归的出口。
我们具体要怎么做呢?
- 定义好递归程序的返回值与参数。
- 想明白怎么缩小规模和本层做什么。
- 想明白递归的出口。
本题的解题思路
首先,我们要merge的是两个有序链表。我们按照步骤来。
第一点,我们定义好递归程序的返回值与参数:
我们merge两个有序链表,肯定是指望递归程序可以返回给我们一个merge好的链表(别觉得这是废话,这很有用)。
那我们参数怎么设计?我们既然要merge两个有序链表,那参数肯定就是两个有序链表。
第二点,我们想明白怎么缩小规模和本层做什么:
链表是从前往后处理的,我们可以给后面执行的递归程序较小的链表来缩小规模。
那本层做什么呢?显然是比较两个节点,哪个小就哪个当头。
第三点,我们想明白递归的出口:
所谓的出口,就是当程序没办法用统一的方式来处理的时候,即异常的情况。
对于这个题目而言,异常显然就是链表A是否走完了?链表B是否走完了?这俩是否同时走完了?
根据这些分析,我们很容易就能写出来递归代码
代码
# 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, list2): # ****出口设计**** if list1 is None and list2 is None: return None if list1 is None: return list2 if list2 is None: return list1 # ****出口设计结束**** # ****本层要做的事情&缩小规模**** if list1.val > list2.val: list2.next = self.mergeTwoLists(list1, list2.next) return list2 else: list1.next = self.mergeTwoLists(list1.next, list2) return list1 # ****本层要做的事情&缩小规模结束****
代码二:
# 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 list1 and list2: if list1.val <= list2.val: list1.next = self.mergeTwoLists(list1.next, list2) return list1 else: list2.next = self.mergeTwoLists(list1, list2.next) return list2 if list1: return list1 if list2: return list2