将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
一气呵成,写出如下代码 ,惊叹一把过了。
思考过程如下:
1、要不要用额外的空间,还是在原来的空间排序组合
2、两个链表为空或者不等长 等等一些特殊情况 怎么处理
3、如果何种方法:突然想到动态规划
动态规划 概念:大事化小,小事化了;以局部最优解,从而达到整体最优。
基于两条链路都是有序,拼接的新链路也是有序的,所以每一步都是最小的节点。也是每步寻找局部最优的过程,从而整体最优。
如何实现动态规划:1、边界值 2、局部最优子结构 3、状态转移方程
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
// 边界条件
if(l1 == null){
return l2;
}
if(l2 == null){
return l1;
}
ListNode head;
// 最优子结构,每次都寻找最小,然后 递归 最小值 和剩余链表;无后效性,当前状态总是最优,而且不影响后面的状态。
if(l1.val < l2.val){
head = new ListNode(l1.val);
head.next = mergeTwoLists(l1.next,l2);
}else{
head = new ListNode(l2.val);
head.next = mergeTwoLists(l1,l2.next);
}
return head;
}
}
还可以优化:优化的空间就是 尽量减少 时间和空间复杂度。
如果不用额外空间,合并两个链表也是可以实现的,就是说 只用两个链表的空间,刚刚好。
空间复杂度为O(1) , 时间复杂度 T(n)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
}
if (l2 == null) {
return l1;
}
ListNode head = new ListNode(0);//头指针
ListNode moveNode = head;//移动指针
while (l1 != null || l2 != null) {
// 每次选择最小的,用移动指针串联起来,移动指针 再循环,以此往复
if (l2 == null || (l1 != null && l1.val <= l2.val)) {
moveNode.next = l1;
l1 = l1.next;
} else if (l1 == null || (l2 != null && l2.val <= l1.val)) {
moveNode.next = l2;
l2 = l2.next;
}
moveNode = moveNode.next;
}
return head.next;
}
}