关于递归条件问题

来源:5-4 复杂的穿针引线 Swap Nodes in Pairs

慕仰7036876

2020-11-30

class Solution {
public ListNode sortList(ListNode head) {
return sortList(head, null);
}

public ListNode sortList(ListNode head, ListNode tail) {
    if (head == null) {
        return head;
    }
    if (head.next == tail) {
        head.next = null;
        return head;
    }
    ListNode slow = head, fast = head;
    while (fast != tail) {
        slow = slow.next;
        fast = fast.next;
        if (fast != tail) {
            fast = fast.next;
        }
    }
    ListNode mid = slow;
    ListNode list1 = sortList(head, mid);
    ListNode list2 = sortList(mid, tail);
    ListNode sorted = merge(list1, list2);
    return sorted;
}

public ListNode merge(ListNode head1, ListNode head2) {
    ListNode dummyHead = new ListNode(0);
    ListNode temp = dummyHead, temp1 = head1, temp2 = head2;
    while (temp1 != null && temp2 != null) {
        if (temp1.val <= temp2.val) {
            temp.next = temp1;
            temp1 = temp1.next;
        } else {
            temp.next = temp2;
            temp2 = temp2.next;
        }
        temp = temp.next;
    }
    if (temp1 != null) {
        temp.next = temp1;
    } else if (temp2 != null) {
        temp.next = temp2;
    }
    return dummyHead.next;
}

}

老师,这是leetcode的官方解,他说的中止递归条件是当链表为空或只有一个节点的时候。链表为空我理解了,但是链表只有一个节点的代码我没看懂,明明有head和tail两个节点呀,最开始tail确实是空,但是在递归过程中不是一直是空呀。这不就代表链表里有两个节点吗?怎么是只有一个节点呢,我调试了一下,确实在递归过程中是有两个节点这种情况在的,而且在调试中是处于只有一个节点时返回head那一行。我有点晕,我知道做递归只用考虑判断终止条件和递归关系式,不需要考虑中间的事,但是这种很明显在递归过程中不是一个节点的也可以不用考虑吗?明明终止条件是只有一个节点,写成代码就是两个节点了,我可以理解在最开始的时候tail作为null,当时确实只有一个节点。但是在递归工程中tail迟早会变成一个有实体的节点,这里也不用考虑吗?

写回答

1回答

liuyubobobo

2020-11-30

初始调用 sortList 的时候,调的是 sortList(head, null),所以 tail == null。head.next == tail 就是看 head.next == null。


head 和 tail 不是两个节点,head 和 tail 是指向 ListNode 的引用,如果指向的是 null,那么通过 head 或者 tail 就无法访问某个节点。


熟练的使用递归以后,可以“不考虑中间的事儿”,但这不代表你不需要理解中间发生了什么。实际上理解递归的过程具体是怎样执行的非常非常重要。我建议你使用小数据量,一个节点,两个节点,三个节点,四个节点,甚至八个节点,用单步跟踪的方式,去仔细观察递归的执行过程到底是怎样的,递归函数一层一层是如何执行的,相应的各个变量是如何变化的。如果你非常透彻的理解了递归,你才能做到“不考虑中间的事儿”,因为其实你在写递归的过程,已经知道中间发生了什么。


我在我的相对专注基础的体系课程中,特地对很多递归过程进行了细致的模拟,就是这个目的,如果有需要可以参考:https://class.imooc.com/sale/datastructure


继续加油!:)

1
0

玩转算法面试-- Leetcode真题分门别类讲解

课程配套大量BAT面试真题,高频算法题解析,强化训练

7408 学习 · 1150 问题

查看课程