Leetcode Week3 Merge Two(k) Sorted Lists
Question
Q1.Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
Example:
Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4
Q2.Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
在解决将k个已排序(从小到大)好的链表合并成一个已排序(从小到大)的链表前,我们先从一个特例开始,即将两个链表合并成一个。
Answer
1.合并两个排列好的链表
问题就是将两个已排序的链表合并成一个,这是归并排序里的一个基本操作。
现在描述以下解决这个问题的算法,用数组来描述。
我们输入两个数组,设为A,B,输出输出C,加入三个计数器Aptr,Bptr,Cptr,初始化为数组开头。
取A[Aptr]和B[Bptr]的较小值拷贝到C的下一个位置,相应的计数器加一,重复该操作,直到某个计数器指向的索引值大于数组的边界。
这时候代表一个数组的元素已经全部拷贝到C的相应位置了,我们将另一个数组剩下的元素拷贝到C里。
回到Leetccode的这个问题,从链表的角度,计数器和链表元素可以用指针来代替,输入和输出数组也可以通过链表头指针访问,下面通过不完整的代码实现这个算法的思想。
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
// first_Node用来输出链表, last_Node用作上面算法描述的计数器(即Cptr),也用作插入元素,代表输出C的最后一个节点
ListNode *first_Node = NULL, *last_Node = NULL;
// 在两个数组都没被拷贝到C时的操作。
while (l1 != NULL && l2 != NULL) {
// 判断A[Aptr](与l1->val一致),B[Bptr](与l2->val一致)哪个较小,将较小的插入到链表C的最后,Aptr和Bptr相应加一(相当于l1,l2)
if (l1->val > l2->val) {
last_Node->next = l2;
last_Node = last_Node->next;
l2 = l2->next;
}
else {
last_Node->next = l1;
last_Node = last_Node->next;
l1 = l1->next;
} }
// 将剩下的元素插入到C的最后
if (l1 == NULL && l2 != NULL) {
last_Node->next = l2;
}
else if (l1 != NULL && l2 == NULL) {
last_Node->next = l1;
}
// 返回链表C
return first_Node;
}
上面的代码已经很能体现代码的具体思想了,剩下的工作就是将代码完善,将边界的情况考虑周全,实际呢,这又是特别麻烦的,一个不小心就会出现问题,比如说访问空指针。我们仔细考虑就会知道,上面代码没有对first_Node进行初始化,所以我们需要对first_Node判断是否为空,空就要初始化为对应的节点。那么在哪里判断呢,很容易想到,我们需要在判断A[Aptr]和B[Bptr]哪个较小后加入,然而这还没结束,将剩下的元素插入到C的最后 后的代码也没有对first_Node(last_Node)是否为空作判断,可又有对last_Node进行操作,这是十分危险的,所以我们也要在这里加入判断。最后完整的代码如下:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode *first_Node = NULL, *last_Node = NULL;
while (l1 != NULL && l2 != NULL) { if (l1->val > l2->val) {
if (first_Node == NULL) {
first_Node = l2;
last_Node = first_Node; } else {
last_Node->next = l2;
last_Node = last_Node->next;
}
l2 = l2->next;
}
else {
if (first_Node == NULL) {
first_Node = l1;
last_Node = first_Node; } else {
last_Node->next = l1;
last_Node = last_Node->next;
}
l1 = l1->next;
} }
if (l1 == NULL && l2 != NULL) {
if (first_Node == NULL)
first_Node = l2;
else
last_Node->next = l2;
}
else if (l1 != NULL && l2 == NULL) {
if (first_Node == NULL)
first_Node = l1;
else
last_Node->next = l1;
}
return first_Node;
}
2.合并k个排列好的链表
好了,有了上面的例子,我们合并k的链表也会有思路了,模仿上面算法的思路,我们可以每次将k个链表的最小值比较一遍,取最小值,将其拷贝到输出链表C中,当然这是可行的,时间复杂度为O(kN),N为最后剩下链表的长度,想了想感觉这有点麻烦,所以我们不妨考虑另一种方法。
按照上一题的思路,其实我们可以两两链表合并,最后合并成一个链表,这样我们就可以重用上面的代码了。两两合并可以是链表1和链表2合并后的链表 再和链表3合并,以此类推,也可以是链表1和链表2合并为链表①,链表3和链表4合并为链表②,依次类推,①又和②合并……,如下图所示。聪明的你一比较就知道后者的效率会高很多,因为合并的次数明显变少了。因此,我们根据后者编写代码:
ListNode* mergeKLists(vector<ListNode*>& lists) {
// 递归终止的条件
if (lists.size() == )
return NULL;
if (lists.size() == )
return lists[]; // 返回链表头节点指针
vector<ListNode*> tmpVec;
// 每两个链表合并
for (int i = ; i < lists.size()/*; i += )
tmpVec.push_back(mergeTwoLists(lists[i], lists[i+]));
// 如果k为奇数,将剩下的最后一个加入到tmpVec中
if (lists.size()% != )
tmpVec.push_back(lists[lists.size()-]);
// 继续合并
return mergeKLists(tmpVec);
}
实际上,这样的解决办法称为分治(divide and conquer),将一个大问题分为几个子问题来解决,在编程里经常用递归实现,上面就有所体现。
Leetcode Week3 Merge Two(k) Sorted Lists的更多相关文章
- 乘风破浪:LeetCode真题_023_Merge k Sorted Lists
乘风破浪:LeetCode真题_023_Merge k Sorted Lists 一.前言 上次我们学过了合并两个链表,这次我们要合并N个链表要怎么做呢,最先想到的就是转换成2个链表合并的问题,然后解 ...
- [Leetcode][Python]23: Merge k Sorted Lists
# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 23: Merge k Sorted Listshttps://oj.leet ...
- 蜗牛慢慢爬 LeetCode 23. Merge k Sorted Lists [Difficulty: Hard]
题目 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity ...
- 【leetcode】Merge k Sorted Lists
Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and descr ...
- 【LeetCode练习题】Merge k Sorted Lists
Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and descr ...
- LeetCode之“链表”:Merge Two Sorted Lists && Merge k Sorted Lists
1. Merge Two Sorted Lists 题目链接 题目要求: Merge two sorted linked lists and return it as a new list. The ...
- LeetCode: Merge k Sorted Lists 解题报告
Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and descr ...
- Leetcode 23.Merge Two Sorted Lists Merge K Sorted Lists
Merge Two Sorted Lists Merge two sorted linked lists and return it as a new list. The new list shoul ...
- LeetCode 023 Merge k Sorted Lists
题目要求:Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and ...
随机推荐
- mac 经常使用的快捷键操作
##### touch bar 作用1: 打开项目的一些快捷操作键. 作用2: 右侧的< 打开有一些以前的常规操作. ##### 手势 ##### mac自带的一些操作 cmd + opt + ...
- python随用随学20200220-异步IO
啥是异步IO 众所周知,CPU速度太快,磁盘,网络等IO跟不上. 而程序一旦遇到IO的时候,就需要等IO完成才能进行才能进行下一步的操作. 严重拖累了程序速度. 因为一个IO操作就阻塞了当前线程,导致 ...
- 【公告】Hello World!
Hi! 这里 是 华中师大一附中 2019 级信息组 官方博客 ! ^_^ 我们将在这里分享一些难题的做法,帮助大家共同学习. 也欢迎同是OIer的你加入我们哦!
- SpringBoot安全管理--(一)SpringSecurity基本配置
简介: Spring Boot针对Spring Security提供了自动化配置方案,因此可以使Spring Security非常容易地整合进Spring Boot项目中,这也是在Spring Boo ...
- SpringBoot整合NoSql--(四)Session共享
简介: 正常情况下,HttpSession是通过Servlet 容器创建并进行管理的,创建成功之后都是保存在内存中.如果开发者需要对项目进行横向扩展搭建集群,那么可以利用一些硬件或者软件工具来做负载均 ...
- P2094运输
-------------------- 链接:Miku ------------------- 这是一道水贪心,很容易想到做法就是把最贵的两个放在一块,让后当成一个重新放回队列 ---------- ...
- 剑指offer-面试题60-n个骰子的点数-动态规划
/* 题目: 计算n个骰子,出现和s的概率. */ #include<iostream> #include<cstdlib> #include<stack> #in ...
- echarts--可拖动的曲线图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- java-重写
重写有要求 1. 方法名:必须和父类被重写的方法名相同 2. 形参列表:必须和父类被重写的方法名相同 3. 返回值类型: A. 基本数据类型和void:要求与父类被重写的返回值数据类型一致 B. 引用 ...
- NIO学习笔记,从Linux IO演化模型到Netty—— 从BIO到epoll模型
本文不涉及具体代码,只分析Linux IO演化的心路历程,学习资料来源网络,不保证一定正确,若有错误,欢迎指出. BIO 服务端创建socket(80端口),文件描述符3号. 当线程调用accept时 ...