LeetCode 合并K个排序链表

合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:

输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
       //代码实现
    }
};

此题解法是在合并两个有序链表的基础上进行扩展的,请先查看我合并两个有序链表的算法博客。这道题就是找到一个非空的链表,然后与一个非空的链表合并,并立即将中间结果更新为一条链表去合并下一条非空链表。

ListNode* mergeKLists(vector<ListNode*>& lists) {
	int length = lists.size();
	if (length == 0) {
		return NULL;
	}
	if (length == 1) {
		return lists[0];
	}
	ListNode *listOne = NULL, *listTwo;
	int begin = 0;
	//寻找第一个非空的头结点
	while (begin < length && lists[begin] == 0) {
		++begin;
	}
	//如果所有的都是空链表
	if (begin >= length) {
		return NULL;
	}
	//初始化为第一个非空的链表
	listOne = lists[begin];
	//不断的将第i个链表与listOne合并,合并后立即更新listOne,然后合并i+1
	for (int i = begin + 1; i < length; ++i) {
		listTwo = lists[i];
		//判断第i个是否为空
		if (listTwo == NULL) {
			continue;
		}
		//非空就与listOne合并
		ListNode *resultList = NULL;//合并后的表头
		ListNode *ptr = NULL;//合并后的表尾
		//首先放入一个节点到结果中
		if (listOne->val < listTwo->val) {
			resultList = ptr = listOne;
			listOne = listOne->next;
		}
		else {
			resultList = ptr = listTwo;
			listTwo = listTwo->next;
		}
		//只有当两个链表都剩余节点时,才可进行比较
		while (listOne != NULL && listTwo != NULL) {
			if (listOne->val < listTwo->val) {
				//将表头添加到结果链表的表尾
				ptr->next = listOne;
				ptr = ptr->next;
				listOne = listOne->next;
			}
			else {
				//将表头添加到结果链表的表尾
				ptr->next = listTwo;
				ptr = ptr->next;
				listTwo = listTwo->next;
			}
		}
		//因为是链表,其本身就是连接好的,无需进行一个一个的移动
		if (listOne != NULL) {
			ptr->next = listOne;
		}
		if (listTwo != NULL) {
			ptr->next = listTwo;
		}
		//将listOne更新为合并之后的结果
		listOne = resultList;
	}
	return listOne;
}

在这里插入图片描述不过时间复杂度有点大。。。
经过翻阅评论区,发现有种比较屌的思路,就是利用并归算法的思路,逐个的将两两相邻的链表合并,最后合成最终的链表。

//struct ListNode {
//	int val;
//	ListNode *next;
//	ListNode(int x) : val(x), next(NULL) {}
//};

ListNode* mergeKLists(vector<ListNode*>& lists) {
	int length = lists.size();
	if (length == 0) {
		return NULL;
	}
	if (length == 1) {
		return lists[0];
	}
	vector<ListNode*> notNullLists;//将原容器中的非空链表挑出
	int count = 0;//非空链表数
	for (vector<ListNode*>::iterator it = lists.begin(); it != lists.end(); ++it) {
		if (*it != NULL) {
			notNullLists.push_back(*it);
			++count;
		}
	}
	if (count == 0) {
		//如果无非空链表
		return NULL;
	}
	if (count == 1) {
		//如果只有一条非空链表
		return notNullLists[0];
	}
	//将非空链表进行合并,从下标0 到 count-1
	ListNode *resultList = mergeKLists(notNullLists, 0, count - 1);
	return resultList;
}

//递归定义从lists下标begin到end的链表合并
ListNode *mergeKLists(vector<ListNode*>& lists, int begin, int end) {
	if (end == begin) {
		return lists[end];
	}
	else if (end == begin + 1) {
		return mergeTwoLists(lists[begin], lists[end]);
	}
	else {
		int mid = (end + begin) / 2;
		ListNode *leftList = mergeKLists(lists, begin, mid);//合并左半部分
		ListNode *rightList = mergeKLists(lists, mid + 1, end);//合并右半部分
		return mergeTwoLists(leftList, rightList);//左右合并
	}
}

//合并两条链表的算法实现
ListNode* mergeTwoLists(ListNode* listOne, ListNode* listTwo) {
	if (listOne == NULL) {
		return listTwo;
	}
	if (listTwo == NULL) {
		return listOne;
	}
	ListNode *resultList = NULL;//合并后的表头
	ListNode *ptr = NULL;//合并后的表尾
	//首先放入一个节点到结果中
	if (listOne->val < listTwo->val) {
		resultList = ptr = listOne;
		listOne = listOne->next;
	}
	else {
		resultList = ptr = listTwo;
		listTwo = listTwo->next;
	}
	//只有当两个链表都剩余节点时,才可进行比较
	while (listOne != NULL && listTwo != NULL) {
		if (listOne->val < listTwo->val) {
			//将表头添加到结果链表的表尾
			ptr->next = listOne;
			ptr = ptr->next;
			listOne = listOne->next;
		}
		else {
			//将表头添加到结果链表的表尾
			ptr->next = listTwo;
			ptr = ptr->next;
			listTwo = listTwo->next;
		}
	}
	//因为是链表,其本身就是连接好的,无需进行一个一个的移动
	if (listOne != NULL) {
		ptr->next = listOne;
	}
	if (listTwo != NULL) {
		ptr->next = listTwo;
	}
	return resultList;
}

在这里插入图片描述
如果不怎么理解该算法,请先参考我合并两条有序链表的算法实现。至于并归思想,后期如果有时间会出并归排序算法,也可自行百度。

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/86259286
今日推荐