剑指offer面试题系列

题目:输入两个递增排序的链表,合并这两个链表并且使新链表的节点仍然是递增排序

分析

有两种想法:一种是新创建一个链表,设置两个指针,分别指向两个链表的头部,每次都取两个指针中的最小元素的内容值,作为新的链表节点的内容。这种方法费时费力。作罢。

另一种就是在原来的两个链表上进行操作。只需要更改表的指针即可完成任务。

但是更改方式不知一种,我只想到一种非递归方式的,实现过程较为繁琐;但是经过剑指offer提醒,又实现了一种递归方式的。哎,递归,又没有想起来。明显递归的方式思路更加清晰而简洁。因为每次都是把最小的元素摘出来,让上一个结点的指针指向它,然后在剩下的部分里继续找这样的节点。

代码

非递归代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

public static void MergeList(ListNode head1, ListNode head2,
ListNode newHead) {
// 分别指向两个表的头结点
ListNode p1 = head1.next;
ListNode p2 = head2.next;
newHead.next = p1.data < p2.data ? p1 : p2; // 确定头结点
ListNode p = new ListNode();

for (p = head1; p1 != null && p2 != null; p = p.next) {
if (p1.data < p2.data) {
p.next = p1;
p1 = p1.next;
} else {
p.next = p2;
p2 = p2.next;
}
}

if (p1 == null) {
p.next = p2;
} else {
p.next = p1;
}

}

递归版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

public static ListNode MergeRecursively(ListNode node1, ListNode node2) {
if (node1 == null)
return node2;
if (node2 == null)
return node1;
ListNode node = new ListNode();
if (node1.data < node2.data) {
node = node1;
node.next = MergeRecursively(node1.next, node2);
} else {
node = node2;
node.next = MergeRecursively(node1, node2.next);
}

return node;
}

总结

需要注意程序的健壮性;
递归的思想还需要领悟,在你一筹莫展时,不要忘了递归这个神奇的武器。