递归第一步就是找到边界,第二步是找到要保存的数据压入栈中,第三步考虑返回值和赋值的顺序
这题简单题递归居然卡了我半天,首先就是要一直递归到最后一个,然后才开始合并,边界就是list1或者list2为空。因为直接修改会丢失listm.next的信息,所以延后修改,让递归函数放回要修改的节点,自己将Next的信息压入递归函数(系统栈中)。list1.Next = mergeTwoLists(list1.Next, list2)
这里已经知道要找一个大的节点,将list1.Next压入栈中。
return list1 放回已经修改过的节点,前面已经递归有序了,当前修改的节点是第一个无序节点。
边界很好判断,单其中一个为nil了,上一个无序的节点只能指向不为nil的节点,很快能写出如下代码。
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
if list1 == nil {
return list2
}
if list2 == nil {
return list1
}
if list1.Val < list2.Val {
mergeTwoLists(list1.Next, list2)
} else {
mergeTwoLists(list1, list2.Next)
}
}
希望list.Next 信息不回消失,则延后赋值next,先记录递归返回的节点
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
if list1 == nil {
return list2
}
if list2 == nil {
return list1
}
if list1.Val < list2.Val {
auto temp = mergeTwoLists(list1.Next, list2)
list1.Next=list2
} else {
auto temp = mergeTwoLists(list1, list2.Next)
list2.Next=list1
}
}
但是list1.Next一定是指向list2吗?不一定,如何list1.Next比list2还小的话是指向list1.Next的。所以很容易写出代码
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
if list1 == nil {
return list2
}
if list2 == nil {
return list1
}
if list1.Val < list2.Val {
list1.Next=mergeTwoLists(list1.Next, list2)
return list1 //让上一层递归指向
} else {
list2.Next=mergeTwoLists(list1, list2.Next)
return list2
}
}
这样处了边界的两种,list1.Next 可能指向两个地方,一个是自己的Next,另外一个是list2。在下次递归返回出正确的节点。
提交
/*
* @lc app=leetcode.cn id=21 lang=golang
*
* [21] 合并两个有序链表
*/
// @lc code=start
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
if list1 == nil {
return list2
}
if list2 == nil {
return list1
}
if list1.Val < list2.Val {
list1.Next = mergeTwoLists(list1.Next, list2)
return list1
} else {
list2.Next = mergeTwoLists(list1, list2.Next)
return list2
}
}
// @lc code=end