ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

算法题,c++,合并K个升序链表,原链表修改链接顺序降低空间复杂度,分治合并降低时间复杂度

2022-02-01 19:02:37  阅读:132  来源: 互联网

标签:结点 ListNode 复杂度 合并 next 链表 升序 Data


算法题,c++,合并K个升序链表,原链表修改链接顺序降低空间复杂度,分治合并降低时间复杂度

题目:leetcode
给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。

链表结点结构:

 typedef struct ListNode {
      int val;
      ListNode *next;
      ListNode() : val(0), next(nullptr) {}
      ListNode(int x) : val(x), next(nullptr) {}
      ListNode(int x, ListNode *next) : val(x), next(next) {}
 }ListNode;

思路:
1、K个链表数据量很大,不适合新建容器或新建链表然后排序,可以利用链表本身的next属性,改变每个结点的后接结点,以达到节省空间的效果。
2、K个链表同时对首结点的数据进行比较不方便,如果是两个链表就可以很方便的使用if进行判断,因此在K个链表中两两相合,两两相合的结果再次两两相合,合到只有一个链表,就是最终的结果了。

代码与每一行的注释,一定注意看注释,看注释,不然有可能看不懂代码的:

//合并两个链表为一个链表
ListNode* AddToOne(ListNode* AList, ListNode* BList)
{
	//判断是否传入的两个链表中有空的链表
	if (!AList || !BList)
	{
		return (AList ? AList : BList);
	}

	//用于组合新链表的链表头
	ListNode* Tail;

	//链表头不能直接使用,新建一个临时结点提供给链表头
	//这个空链表头还用于找到链表的头,避免在合并完以后无法获取到链表的起点
	//临时结点还用于返回链表头,通过return Head.next
	ListNode Head;
	Tail = &Head;

	//用于遍历两个链表的所有内容和比较链表结点数据的指针
	ListNode* pA = AList;
	ListNode* pB = BList;

	//当两个遍历的结点A,B都有值时,说明两个链表中的数据还没有遍历完,
	//只要有一个遍历完了,就表示两个合并为一个了,且无法继续进行比较了
	//因此while循环的判断条件是两个结点都有值而不是空
	while (pA && pB)
	{
		//哪个小就把哪个放到新链表的尾部
		if (pA->val < pB->val)
		{
			Tail->next = pA;
			pA = pA->next;
		}
		else
		{
			Tail->next = pB;
			pB = pB->next;
		}
		//装入尾部后将新链表的当前结点向后移,保持在最后位
		Tail = Tail->next;
	}

	//判断结束后,一个链表变成空了,剩下还有一部分链表需要另外加入到新链表
	Tail->next = (pA ? pA : pB);

	return Head.next;
}

//使用分治算法将链表vector进行分治合并

//每一次合并只能合并两个下标的链表,将两个链表的所在下标表示为left,right
ListNode* merge(vector<ListNode*>& Data,int left,int right)
{
	//当左下标和右下标相等时,返回该下标对应的链表就可以
	if (left == right)
	{
		return Data[left];
	}

	//当左下标和右下标紧跟着时,就可以合并了,然后将合并的结果返回
	else if(left + 1 == right)
	{
		return AddToOne(Data[left], Data[right]);
	}

	//当左下标和右下标没有相等,没有紧跟着时,递归下去
	//向下递归的规律为:从最左边到中间的合并,中间后一个结点到最右边的合并,得到的两个链表合并后将链表返回
	else
	{
		return AddToOne(merge(Data, left, (left + right) / 2 ), merge(Data, (left + right) / 2 + 1, right));
	}
}

ListNode* mergeKLists(vector<ListNode*>& Data)
{
	//传入的vector有可能是个空的,为了避免后面的size-1为负数,有必要对size的值进行判断
	if (Data.size() == 0)
	{
		return NULL;
	}
	return merge(Data, 0, Data.size() - 1);
}

标签:结点,ListNode,复杂度,合并,next,链表,升序,Data
来源: https://blog.csdn.net/ganfanren00001/article/details/122765382

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有