前言
本博文部分图片, 思路来自于剑指offer 或者编程珠玑
问题描述
现在有两个有序链表的头结点, 试图将两个链表归并到一个链表中, 是一道 很常见的一道题目
思路
两种思路, 一种基于循环, 一种基于递归, 后者简洁的多
思路一 : 首先判断两个链表的第一个结点的大小 确定头结点, 然后利用一个循环进行归并, 直到归并到某一个链表末尾, 然后接上另外一个链表的剩余数据即可
思路二 : 判断两个链表的第一个结点的大小 获取较小的结点[这里 假设是从小到大], 然后设置该节点的下一个结点为归并该节点剩余的链表 和另外的一个链表的结果, 返回该较小节点 [注意这里的递归]
参考代码
/**
* file name : Test01MergeTwoList.java
* created at : 8:28:20 PM Jun 5, 2015
* created by
*/
package com.hx.test05;
public class Test01MergeTwoList {
// 归并两个有序链表
public static void main(String []args) {
LinkedList ll01 = new LinkedList();
LinkedList ll02 = new LinkedList();
int max = 20;
for(int i=0; i<max; i+=3) {
ll01.add(i);
}
for(int i=1; i<max; i+=2) {
ll02.add(i);
}
Node head = mergeTwoList01(ll01.first(), ll02.first());
// Node head = mergeTwoList02(ll01.first(), ll02.first());
Node tmp = head;
while(tmp != null) {
Log.logWithoutLn(tmp.getData() + " ");
tmp = tmp.getNext();
}
}
// 归并两个顺序的链表
// 先确定头结点, 更新头结点所在的链表的索引到下一个元素, 设置cur索引为头结点[单独确立头结点]
// 开始归并 知道到达任意链表的末尾, 如果比较两个链表的当前元素, 设置cur.next为较小的元素, 然后更新该较小元素所在的链表的索引, 继续比较
// 当遍历到某一个链表的末尾之后 设置cur.next为另一个链表的索引
public static Node mergeTwoList01(Node first, Node first2) {
if(first == null) {
return first2;
}
if(first2 == null) {
return first;
}
Node res = null, cur = null;
if(first.getData() < first2.getData()) {
res = first;
first = first.getNext();
} else {
res = first2;
first2 = first2.getNext();
}
cur = res;
while(first != null && first2 != null) {
if(first.getData() <= first2.getData() ) {
cur.setNext(first);
first = first.getNext();
} else {
cur.setNext(first2);
first2 = first2.getNext();
}
cur = cur.getNext();
}
if(first == null) {
cur.setNext(first2);
} else {
cur.setNext(first);
}
return res;
}
// 递归版本的合并两个有序链表
public static Node mergeTwoList02(Node first, Node first2) {
if(first == null) {
return first2;
}
if(first2 == null) {
return first;
}
Node res = null;
if(first.getData() < first2.getData()) {
res = first;
res.setNext(mergeTwoList02(first.getNext(), first2) );
} else {
res = first2;
res.setNext(mergeTwoList02(first, first2.getNext()) );
}
return res;
}
}
效果截图
总结
这种思路 应该在我们学习归并排序的时候, 就应该使用过吧, 因为递归处理省略了对于链表遍历的循环, 以及对于两个链表中某一个链表为空的结尾的处理[传递到了下一次方法递归来处理], 所以 看起来简洁的多
注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!