题目:
将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
输出:1->1->2->3->4->4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-two-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
链接:https://leetcode-cn.com/problems/merge-two-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解体方法:暴力法和递归:
暴力法思路:
首先链表这种数据结构是一个只能从头访问的,本题中,因为两个链表中的头节点都要先进行比较之后才能确定最后输出的节点谁是头节点,这种情况在链表中比较普遍,所以我们可以new一个dummy节点出来,在设置一个pre节点进行遍历,最后返回dummy.next即可。
代码如下:
class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode dummy=new ListNode(0); //new一个dummy节点,里面的值不重要。 ListNode pre=dummy; //pre节点指向dummy进行遍历 while(l1!=null && l2!=null){ if(l1.val<=l2.val){ pre.next=l1; l1=l1.next; } else{ pre.next=l2; l2=l2.next; } pre=pre.next; //移动到下一个指针出 } pre.next=l1==null?l2:l1; return dummy.next; //最后返回dummy.next } }
复杂度分析:
时间复杂度:O(n+m):最坏的情况下我们需要遍历两条链表所有节点。
空间复杂度:O(1):只需要new一个dummy节点
递归法思路:
递归递归,一看就会一写就废。。。。
考虑递归结束条件:当l1和l2中任意一个链表为空时就结束;
根据递归的剥洋葱理论:一层一层的深入,借用leetcode评论区的图进行说明
-------------
上面就是洋葱一层一层深入过程,可以很轻松的进行递归建模 min(val).next=mergeTwoLists(min.next, other);
--------
上面就是返回的时候,每次比较的较小值作为上一层洋葱要链接的值,也是是需要返回的值:min(val).next=mergeTwoLists(min.next, other)中mergeTwoLists(min.next, other)需要返回的是min.next和other中val较小的指针!
所以我们可以写出代码:
class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if(l1==null){ //边界条件 return l2; } if(l2==null){ return l1; } if(l1.val<=l2.val){ l1.next=mergeTwoLists(l1.next,l2); //深入过程 return l1; //这里返回的是上一层要链接的节点 } else{ l2.next=mergeTwoLists(l1,l2.next); return l2; } } }
复杂度分析:
时间复杂度:O(m+n):最坏的情况下需要遍历比较两条链表所有的节点
空间复杂度:O(m+n):在每层剥洋葱的过程中需要用栈保存每层返回的指针,最坏的情况下需要m+n个
总结:
可以看出递归的优势不在于性能,而在于代码简洁,一个典型的用时间换空间的算法。