leetcode 第23题:关于递归的一些思考与应用
来源:互联网 发布:mac启动磁盘空间不足 编辑:程序博客网 时间:2024/05/07 08:59
题目大意:
给出若干已经排好序链表的头节点指针,将它们合并成一个成序的链表,返回其头结点指针。
示例:
给定链表:1->2->3 和 4->6->8,则应当返回链表 1->2->3->4->6->8的头节点指针。
解题思路:
一开始看到这道题,我觉得会比较复杂。因为要排成有序链表需要先逐个比较,再将节点插入对应的位置。后来联想到之前使用过的哈希表,变换思路如下:遍历每一个链表,将每个节点的值插入到容器set中,同时建立一个哈希表,存储节点的值和它出现的次数。所有链表遍历结束之后,所有出现过的节点值都保存到了set中,并且按顺序排好。此时,只需要再遍历一遍set,再找到哈希表中对应出现的次数,就可完成合并链表的创建。实现代码如下:
以上代码在本地通过了测试,但上传到leetcode时,却出现了编译错误。似乎是因为它不允许在类外创建全局变量。回过头看题目,我发现有一个重要条件完全没有派上用场:给出的链表是已经排好序的,这说明算法复杂度肯定不是最优的。并且,实现代码中,我自行创建了集合、映射表,又新建了节点,导致算法的空间复杂度也会很大,进一步降低了其实用性。
在discuss中,高票的C++解答是基于之前的两链表合并问题的拓展。AC代码如下:
/** 1. Definition for singly-linked list. 2. struct ListNode { 3. int val; 4. ListNode *next; 5. ListNode(int x) : val(x), next(NULL) {} 6. }; */class Solution {public: ListNode* mergeKLists(vector<ListNode*>& lists) { if(lists.size()==0) return nullptr; while(lists.size()>1) { lists.push_back(merge2Lists(lists[0],lists[1])); lists.erase(lists.begin()); lists.erase(lists.begin()); } return lists.front(); } ListNode* merge2Lists(ListNode* l1, ListNode* l2){ //连接两个链表 if(l1==nullptr) return l2; //如果是空指针,则返回l1 if(l2==nullptr) return l1; if(l1->val>l2->val) { l2->next=merge2Lists(l1,l2->next); //确定下下一节点 return l2; //返回比较结果 } else { l1->next=merge2Lists(l1->next,l2); return l1; } }};
可以看出,它在时间和空间复杂度上都更加优越。经仔细分析,在合并两个链表时,它是通过递归的方式寻找当前节点的下一节点,直到有一条链表为空为止。
对我来说,递归一直是一个理解上的难点。因此我试着从几个例子中去理解它的意思。以链表1:1->2->3和链:2:2->3->4为例:
1. 首先需要寻找合成链表的头结点,换言之,两个链表头结点中值较小的那一个,即1。
2. 随后寻找下一节点。此时,需要比较当前节点在本链表中的下一节点与另一链表的当前节点值的大小,较小者为下一节点。此处,为2和2,不妨取链表2中的“2”作为下一节点。
3. 再次寻找下一节点,与步骤2类似,比较2与3,链表1中的“2”成为下一节点
……
4. 重复以上过程,当需要确定链表1中的3的下一节点时,发现它在本链表中已经是最后一个节点。因此另一链表中的节点自动成为下一节点。由于两个链表本身是成序的,因此也无需进行下一步的搜索,即可得到结果。
如此,只需要用一个函数merge2Lists即可实现上述过程。不难发现,如果采用顺序的思维,是很容易理解以上的代码的。但轮到自己去实现时,仍然很难完成。归根结底,是因为习惯了先程序中得到结果,再将结果进行进一步的处理的方式,不习惯递归的思维方法——先进行处理,再将结果逐步回带。
- leetcode 第23题:关于递归的一些思考与应用
- 关于递归的一些思考
- 关于机器学习应用的一些思考
- 关于长尾应用的一些思考
- 关于递归的思考
- 关于递归的思考
- 关于递归的一些简单应用
- 关于类似与俄罗斯娃娃的题的一些思考
- 白书 - 拓扑排序 及 关于递归、coding的一些思考
- 关于Scalability的一些思考与疑问
- 关于限流的一些学习与思考
- 关于java与C的一些思考
- 关于GPS与GIS的一些思考
- 关于第5周反向传播算法的一些争论与思考
- 关于混合应用开发的未来的一些思考
- 关于Hadoop结合RDBMS应用的一些思考
- 关于Hadoop结合RDBMS应用的一些思考
- 关于Hadoop结合RDBMS应用的一些思考
- 动态链接库与应用
- 首写文件夹突然丢失;在回收站未找到
- ionic angular 与原生进行交互
- apicloud头像上传
- Linux个发型版本
- leetcode 第23题:关于递归的一些思考与应用
- C# 反射、与dynamic最佳组合
- 在附近小程序中展示你的小程序-微信小程序开发-视频教程21
- 代码干货 | 开源日志库Logger的使用
- Java多线程--异步执行框架Executor
- Java基本数据类型介绍
- React 入门实例教程
- Ubuntu 14.04 上安装 CUDA 7.5/8.0 超详细教程
- Linux服务器安全策略实战免费送给运维工程师