题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。例如输入图中的链表1和链表2,则合并以后的升序链表3所示。面试
这是一个常常被各公司采用的面试题。在面试过程当中,咱们发现应聘者最 容易犯两个错误:一是在写代码以前没有对合并的过程想清楚,最终合并出来的链表要么中间断开要么并无递增排序;二是代码的鲁棒性方面存在问题,程序一旦 有特殊的输入(如空链表)就会崩溃。接下来分析如何解决这个问题。函数
首先分析合并两个链表的过程。咱们的分析从合并两个链表的头结点开始。链表1的头结点的值小于链表2的头结点的值,所以链表1的头结点将是合并后链表的头结点,如图所示:.net
咱们继续合并两个链表中剩余的结点。在两个链表中剩下的结点依然是排 序的,所以合并这两个链表的步骤和前面的步骤是同样的。咱们仍是比较两个头结点的值。此时链表2的头结点的值小于链表1的头结点的值,所以链表2的头结点 的值将是合并剩余结点获得的链表的头结点。咱们把这个结点和前面合并链表时获得的链表的尾节点连接起来,如图所示。指针
当咱们获得两个链表中值较小的头结点并把它连接到已经合并的链表以后,两个链表剩余的结点依然是排序的,所以合并的步骤和以前的步骤是同样的。这就是典型的递归的过程,咱们可疑定义递归函数完成这一合并过程。排序
接下来咱们来解决鲁棒性的问题。每当代码试图访问空指针指向的内存时 程序就会崩溃,从而致使鲁棒性问题。在本题中一旦输入空的链表就会引入空的指针,所以咱们要对空链表单独处理。当第一个链表是空链表,也就是它的头结点是 一个空指针时,那么把它和第二个链表合并,闲人合并的过程就是第二个链表。一样,当输入的第二个链表的头结点是空指针的时候,咱们把它和第一个链表合并得 到的结果就是第一个链表。若是两个链表都是空链表,合并的结果是获得一个空链表。递归
下面是Java代码的实现:内存
package cglib;
class ListNode
{
int data;
ListNode nextNode;
}get
public class DeleteNode {
public static void main(String[] args) {
ListNode head1=new ListNode();
ListNode second1=new ListNode();
ListNode head2=new ListNode();
ListNode second2=new ListNode();
ListNode third2=new ListNode();
head1.nextNode=second1;
head2.nextNode=second2;
second2.nextNode=third2;
head1.data=1;
second1.data=3;
head2.data=2;
second2.data=2;
third2.data=2;
DeleteNode test=new DeleteNode();
ListNode result=test.reverseList(head1, head2);
System.out.println(result.nextNode.nextNode.nextNode.nextNode.data);
}
public ListNode reverseList(ListNode head1,ListNode head2){
if(head1==null&&head2!=null){
return head2;
}
else if(head2==null&&head1!=null){
return head1;
}
else if(head2==null&&head1==null){
return null;
}
else
{
ListNode mergeHead=null;
if(head1.data<head2.data){
mergeHead=head1;
mergeHead.nextNode=reverseList(head1.nextNode,head2);
}else{
mergeHead=head2;
mergeHead.nextNode=reverseList(head1, head2.nextNode);
}
return mergeHead;
}
}
}class