leetcode上有合并链表的题,大概是说将k个升序链表合成1个升序链表。(附上原题)
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-two-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法有很多种,但是如果加上限定:原地合并(不创建新的链表),就有点说法了,先上一个这个题的我觉得贼6的解:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
if(l1==NULL)
return l2;
if(l2==NULL)
return l1;
if(l1->val < l2->val){
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}else{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
这是一个很标准的递归求解方法;后来我在论坛里看到一个老哥发了一个贴:
看完完之后感觉很熟悉,但是合并之后的增减性变了。那么已开始是无法确定链表的头结点的(不知道两个子链表的结尾谁的大)。这时候需要自底向上解决问题,所以我使用尾递归来尝试解决这个问题。总体思想是:merge返回合并之后的尾节点,然后尾节点指向当前L1和L2的较大值,再返回较小值作为新的尾节点。(想象一下把拉链从底向上拉起来的过程)
List* merge(List* l1, List* l2, List *head) {
if (!(l1 || l2)) {
head->next = NULL;
return head;
}
if ((l1 != NULL) && (l2 == NULL)) {
List* pre = merge(l1->next, l2, head);
l1->next = NULL;
pre->next = l1;
if (!flag) {
head->next = l1;
FOUND_HEAD;
}
return l1;
}
if ((l1 == NULL) && (l2 != NULL)) {
List* pre = merge(l1, l2->next, head);
l2->next = NULL;
pre->next = l2;
if (!flag) {
head->next = l2;
FOUND_HEAD;
}
return l2;
}
else if (l1->val > l2->val) {
List* pre = merge(l1, l2->next, head);
if (pre == l1) {
pre->next = l2;
}
else {
pre->next = l1;
l1->next = l2;
}
return l2;
}
else {
if (l2->val == l1->val) {
List* pre = merge(l1->next, l2->next, head);
pre->next = l2;
l2->next = l1;
return l1;
}
List* pre = merge(l1->next, l2, head);
if (pre == l2) {
pre->next = l1;
}
else {
pre->next = l2;
l2->next = l1;
}
return l1;
}
}
递归的程序分支和第一道题是一样的,只是这次递归需要修改把结点指针重新赋值(容易写懵逼)
测试一波:
int main()
{
int i, j;
List* l1, *l2;
l1 = (List*)malloc(sizeof(List));
l1->val = 0;
l1->next = NULL;
l2 = (List*)malloc(sizeof(List));
l2->val = 2;
l2->next = NULL;
List* pre;
pre = l1;
for (i = 1; i < 5; i++) {
List* current = (List*)malloc(sizeof(List));
current->next = NULL;
current->val = i*3;
pre->next = current;
pre = current;
}
pre = l2;
for (i = 3; i < 10; i++) {
List* current = (List*)malloc(sizeof(List));
current->next = NULL;
current->val = i;
pre->next = current;
pre = current;
}
List* current = l1;
while (current != NULL) {
printf("%d->", current->val);
current = current->next;
}
printf("NULL\n");
current = l2;
while (current != NULL) {
printf("%d->", current->val);
current = current->next;
}
printf("NULL\n");
List* head = (List*)malloc(sizeof(List));
head->next = NULL;
current = merge(l1,l2,head);
current->next = NULL;
current = head->next;
while (current != NULL) {
printf("%d->",current->val);
current = current->next;
}
printf("NULL\n");
return 0;
}