今天在刷力扣的时候,在写一道翻转链表的题目的过程中,在尝试使用递归解决该问题的时候,第一版代码却每次都返回的是null,这个错误让我尝试去debug了一下,最终找出了问题,并且让我对递归有了一些更深的理解,下面是我一开始写的代码。
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution { public ListNode reverseList(ListNode head) { ListNode pre = null; ListNode cur = head; reverse(pre, cur); return pre; } public void reverse(ListNode pre, ListNode cur) { if (cur == null) { // 递归基,当cur为空时,表示已到达链表末尾,直接返回 return; } ListNode next = cur.next; // 保存当前节点的下一个节点 cur.next = pre; // 反转当前节点的指向 reverse(cur, next); // 递归地处理下一个节点 }
}
我考虑的是java中的链表传递的是引用所以我在reverse递归结束后,pre应该正好是翻转链表后的第一个结点,所以我在递归后将它返回给最终答案,结果无论输入是什么,输出都是null。
在debug后,我发现,
在最后检测到cur是null之时,pre所指向的链表是我们最后要得到的答案,在这个时候执行return,但是return到的是上一个reverse函数栈,在该函数中,pre链表的结果还不是最终答案,就这样一步步回退回去之后,直到恢复成了原样,并从最后的“}}”退出,此时pre又变成了原来的空值,所以这就导致了无论我的输入是什么,输出都是空值的原因。
将代码修改如下,在最后找到目标答案值得时候,一层层返回这个答案值,而不是返回空值得回退,这样可以将最后得答案值返回给进入循环时的pre,修改后的代码如下所示。
/*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val = val; }* ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution { public ListNode reverseList(ListNode head) { ListNode pre = null; ListNode cur = head; return reverse(pre, cur); } public ListNode reverse(ListNode pre, ListNode cur) { if (cur == null) { // 递归基,当cur为空时,表示已到达链表末尾,直接返回 return pre; } ListNode next = cur.next; // 保存当前节点的下一个节点 cur.next = pre; // 反转当前节点的指向 return reverse(cur, next); // 递归地处理下一个节点 }
}