LeetCode ---- 合并两个有序链表

 这是我刷了这么久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。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本题要求合并两个有序链表。对于链表中的每一个节点,由于链表有序的,所以可以将两个链表中的节点按照大小顺序进行比较,然后逐个将较小的节点链接上去,最终得到一个新的有序链表。 使用Rust语言实现这个问题,需要首先定义一个链表节点的结构体,包含node值以及next指针。然后定义一个函数来合并两个有序链表,输入为两个链表的头节点指针,输出为新的有序链表的头节点指针。 在合并过程中,首先需要判断两个链表的头节点哪一个较小,将较小的节点作为新链表的头节点,并将该节点的next指针指向递归调用合并函数的结果。递归结束条件为其中一个链表为空,则将另一个链表直接链接到新链表上。 完整代码如下: ```rust // 定义链表节点结构体 #[derive(Debug)] struct ListNode { val: i32, next: Option<Box<ListNode>>, } impl ListNode { fn new(val: i32) -> Self { ListNode { val, next: None } } } // 合并两个有序链表 fn merge_two_lists(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> { match (l1, l2) { (None, None) => None, // 两个链表均为空 (l1, None) => l1, // 其中一个链表为空,直接返回另一个链表 (None, l2) => l2, (Some(mut l1), Some(mut l2)) => { if l1.val < l2.val { l1.next = merge_two_lists(l1.next, Some(l2)); Some(l1) } else { l2.next = merge_two_lists(Some(l1), l2.next); Some(l2) } } } } // 测试代码 fn main() { let l1 = Some(Box::new(ListNode { val: 1, next: Some(Box::new(ListNode { val: 2, next: Some(Box::new(ListNode { val: 4, next: None, })), })), })); let l2 = Some(Box::new(ListNode { val: 1, next: Some(Box::new(ListNode { val: 3, next: Some(Box::new(ListNode { val: 4, next: None, })), })), })); let merged = merge_two_lists(l1, l2); println!("{:?}", merged); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值