前言:
此刻看官们对“链表求最小值递归算法”大体比较注重,各位老铁们都需要了解一些“链表求最小值递归算法”的相关文章。那么小编也在网上收集了一些有关“链表求最小值递归算法””的相关资讯,希望咱们能喜欢,朋友们快快来了解一下吧!题目描述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
解题思路
按照题目的描述,给定的两个链表各自本身是有序的,我们要将它合并成一个有序链表,也就是要把这两个链表合到一起重新排序得到最终的结果,这道题我提供了两种解法,非递归解法和递归解法。
非递归解法
首先自己实现一个单链表ListNode:
public class ListNode<E> { public ListNode next; public E e; public ListNode(E e) { this(e, null); } public ListNode(E e, ListNode next) { this.e = e; this.next = next; } public ListNode() { this(null, null); }复制代码
非递归代码
public class MergeList { public static void main(String[] args) { MergeList mergeList = new MergeList(); ListNode node1 = new ListNode(1); ListNode node11 = new ListNode(3); node1.next = node11; node11.next = node111; ListNode node2 = new ListNode(2); ListNode node22 = new ListNode(4); ListNode node222 = new ListNode(6); node2.next = node22; node22.next = node222; ListNode node = mergeList.mergeTwoLists(node1, node2); } public ListNode mergeTwoLists(ListNode<Integer> l1, ListNode<Integer> l2) { //设置虚拟头节点 ListNode<Integer> dummy = new ListNode<Integer>(0), pp = dummy; while (l1 != null && l2 != null) { if (l1.e <= l2.e) { pp.next = l1; pp = pp.next; l1 = l1.next; } else { pp.next = l2; pp = pp.next; l2 = l2.next; } } if (l1 != null) { pp.next = l1; } if (l2 != null) { pp.next = l2; } return dummy.next; }}复制代码
非递归解法总体思路就是通过 while 循环对 l1 和 l2 链表的值进行一一比较,假设第一轮比较 l1 的值是最小的,就将 l1 放入结果链表中,然后对 l1 进行移动到下一位,两者继续比较,依次类推,直到 l1 , l2 其中一方为空,跳出循环,跳出循环后因为两者肯定有一方还有值,直接将当前结果链表节点的next节点指向不为空的链表,最终就得到了排序后的结果,进行返回。
通过动态图来进行演示:
递归解法
/** * 递归解法 * * @param l1 * @param l2 * @return */ public ListNode mergeTwoLists(ListNode<Integer> l1, ListNode<Integer> l2) { if (l1 == null) { return l2; } else if (l2 == null) { return l1; } else if (l1.e < l2.e) { l1.next = mergeTwoList(l1.next, l2); return l1; } else { l2.next = mergeTwoList(l1, l2.next); return l2; } }复制代码
递归的终止条件就是两个链表 l1 , l2 其中有一个为空时就终止然后往上回溯,最终返回答案。
那怎么去递归的呢?
我们判断 l1 和 l2 头节点哪个更小,然后将较小节点的 next 指针指向其余节点的合并结果,就是继续调用递归方法,直到满足终止条件。
递归代码非常简洁,但是可能看起来很绕,一层一层的递归,一不小心就容易绕晕了,我们来把这个递归进行解剖,一步一步进行分析:
l1是1->3, l2 是 2->4->6
第一次方法调用:
l1 的头节点是1,l2 是3,所以会将 l1.next 指向下次的方法调用
此时:结果链表为:l1->l1.next=mergeTwoList
l1.next = mergeTwoList(l1.next, l2); return l1;复制代码
第二次方法调用:
将l1的第二个节点和l2的头节点进行比较
3比2大,所以l1.next就是 l2 的头节点
l2.next = mergeTwoList(l1, l2.next); return l2;复制代码
结果链表: 继续顺延为:l1 -> l2-> l2.next=mergeTwoList
第三次方法调用: 就是 l2 的第二个节点和 l1 的第二个节点进行比较:
4比3大,因此l2的next节点就要l1的第二个节点
结果链表: l1-> l2->l1.next->l1.next.next = mergeTwoList
第四次方法调用:
此时l1没有第三个节点,所以l1当前节点为空,开始往上回溯:
因此 l1的空节点 就是l2的第二个节点
结果链表: l1-> l2 -> l1.next -> l2.next
那么最终结果值就为:1->2->3->4->6
总结
两种解法,可能第二种递归解法比较难以理解,我的建议是一步一步debug,看下值的变化,一步一步跟踪,就能彻底理解了,在这里给大家出个思考题,如果是多个有序链表进行合并,我们应该怎么操作呢?关注我,下篇文章为你解答。
标签: #链表求最小值递归算法