剑指offer------合并两个排好序的链表(递归&&非递归版本 去重&&非去重 史上最全)

题目:

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调递增规则。

例子

如:链表1:1->3->5->9;链表2:2->4->6;合并后为:1->2->3->4->5->6->9。

链接:

剑指Offer:17题

思路标签:

  • 数据结构:链表
  • 算法:递归

解答:

1. C++

  • 对问题进行分解。
  • 每次以两个链表头节点中的小值作为合并链表的下一个节点。
  • 每次合并的操作都是相同的,故使用递归,或者不用递归。
  • 注意代码的鲁棒性,即输入链表为空的情况。

A.递归版本

  1. 没有去重:
/*
struct Listnode
{
	int value;
	struct Listnode *next
}
*/
Listnode* Merge(Listnode*pHead1,Listnode*pHead2)
{
	if(pHead1==NULL)
		return pHead2;
	else if(pHead2==NULL)
		return pHead1;
		
	Listnode* pMerge=NULL;  //新链表的节点
	if(pHead1->value<pHead2->value)
	{
		pMerge = pHead1;
		pMerge->next=Merge(pHead1->next,pHead2);
	}
	else
	{
		pMerge = pHead2;
		pMerge->next=Merge(pHead1,pHead2->next);
	}
	
	return pMerge;
	
}

     2.去重:

//去重
Listnode* Merge(Listnode*pHead1,Listnode*pHead2)
{
	if(pHead1==NULL)
		return pHead2;
	else if(pHead2==NULL)
		return pHead1;
		
		
	Listnode* pMerge=NULL;  //新链表的节点
	
	
	if(pHead1->value<pHead2->value)
	{
		pMerge = pHead1;
		pMerge->next=Merge(pHead1->next,pHead2);
	}
	
	else if(pHead1-next>pHead2->next)
	{
		pMerge = pHead2;
		pMerge->next=Merge(pHead1,pHead2->next);
	}
	
	else
	{
		//相等时只插入一个
		Listnode* s = pHead2;
		pMerge = pHead1;
		pMerge->next=Merge(pHead1-next,pHead2->next);
		
		free(s);
	}

	return pMerge;
}

B.非递归:

  1. 不去重:
//链表存储
#define NULL 0
typedef int ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode *next;
}LNode, *LinkList;
void mergeList(LinkList &La,LinkList &Lb,LinkList &Lc)
{
	Lc =La;  //将La的头节点作为Lc的头节点
	LinkList pa=La->next;
	LinkList pb=Lb->next;
	LinkList pc=Lc;    //pc总是指向Lc的最后一个节点
	
	while(pa&&pb)
	{
		if(pa->data<pb->data)
		{
			pa->next = pa;
			pa=pa;
			pa=pa->next;
		}
		else
		{
			pc->next=pb;
			pc=pb;
			pb=pb->next;
		}
	}
	pc->next=pa?pa:pb; //插入余段
	free(Lb);//释放Lb的节点
}

     2.去重

void unionList(LinkList &La, LinkList &Lb){
	LinkList pa = La->next;
	LinkList pb = Lb->next;
	LinkList pc = La;//pc总是指向并集列表的最后一个节点
 
	while(pa&&pb){
		if(pa->data < pb->data){
			pc->next = pa;
			pc = pa;
			pa = pa->next;
		}else if(pa->data > pb->data){
			pc->next = pb;
			pc = pb;
			pb = pb->next;
		}else{//a==b,只插入其中之一
			LinkList s = pb;
 
			pc->next = pa;
			pc = pa;
			pa = pa->next;
			pb = pb->next;
 
			free(s);
		}
	}
	pc->next = pa?pa:pb;//插入剩余段
	free(Lb);//释放Lb的头节点
}

1.参考资料:《剑指offer》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值