这是我刷了这么久LeetCode以来,最让我无语的一道题。合并两个有序链表,题确实不难。写完之后,一直编译不过,出现下面的傻逼问题,合并完之后就是少一个数。分析了两遍,甚至画了整个代码合并过程的图,觉得代码没有什么问题。但还是运行不过,让我真的很难受。实在没办法,就去VS下写了完整的单链表合并,一模一样的代码,VS下面运行出来的结果一点毛病都没有。 让我真的有一点怀疑,LeetCode里面的编译器真的是个傻逼。
不管怎么样,目的还是学习。所以还是先看一下题目吧!
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
合并的过程很好想,因为两个链表本身有序,所以不用考虑万一链表后面出现更大的数。这个过程简单来说就是先将新链表指向两个链表第一个节点值小的那个链表。然后依次遍历两个链表,将较小值的节点链到新链表后就行。思路就是这个思路,具体实现还是看这个非递归的代码比较合适。
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
struct ListNode
{
int val;
struct ListNode* next;
};
//初始化
void InitList(struct ListNode* l1)
{
assert(l1 != NULL);
l1->next = NULL;
}
//申请节点
static struct ListNode *GetNode(int val)
{
struct ListNode*pGet = (struct ListNode*)malloc(sizeof(struct ListNode*));
assert(pGet != NULL);
pGet->val = val;
pGet->next = NULL;
return pGet;
}
//尾插
int Insert_tail(struct ListNode* l1, int val)
{
assert(l1 != NULL);
struct ListNode *p = l1;
while (p->next != NULL)
{
p = p->next;
}
struct ListNode *pGet = GetNode(val);
p->next = pGet;
return 1;
}
//合并
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
assert(l1 != NULL && l2 != NULL);
assert((l1->next != NULL) && (l2->next != NULL));
struct ListNode *p1 = l1->next;
struct ListNode *p2 = l2->next;
struct ListNode *new_List = (p1->val <= p2->val) ? l1 : l2;//比较两个有序链表哪个的第一个值小,小的链表将链表地址赋给新链表
struct ListNode *tmp = new_List;
while ((p1 != NULL) && (p2 != NULL))
{
//哪个的值小,就连接到新链表后
if (p1->val <= p2->val)
{
tmp->next = p1;
p1 = p1->next;
}
else
{
tmp->next = p2;
p2 = p2->next;
}
tmp = tmp->next;
}
//出循环有可能其中一个链表的值还没有判断完,那么执行如下操作,将其直接链到新链表就OK
if (p1 != NULL)
{
tmp->next = p1;
}
if (p2 != NULL)
{
tmp->next = p2;
}
return new_List;
}
//打印
void Show(struct ListNode* plist)
{
assert(plist != NULL);
struct ListNode *p = plist;
while (p->next != NULL)
{
printf("%d ", p->next->val);
p = p->next;
}
printf("\n");
}
int main()
{
struct ListNode l1;
struct ListNode l2;
InitList(&l1);
InitList(&l2);
Insert_tail(&l1, 1);
Insert_tail(&l1, 2);
Insert_tail(&l1, 4);
Insert_tail(&l2, 1);
Insert_tail(&l2, 3);
Insert_tail(&l2, 4);
Show(&l1);
Show(&l2);
struct ListNode* new_list = mergeTwoLists(&l1,&l2);
Show(new_list);
return 0;
}
代码运行结果如上,至于为什么和LeetCode上运行结果不一样。我猜想可能是因为编译器,或者链表初始化的方式有所不同,导致运行结果又那么一丢丢小问题!但是没关系,问题不大,有一个正确的思路就OK。