剑指Offer - 九度1524 - 复杂链表的复制
剑指Offer - 九度1524 - 复杂链表的复制
2014-02-07 01:30
- 题目描述:
-
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点)。
- 输入:
-
输入可能包含多个测试样例,输入以EOF结束。
对于每个测试案例,输入的第一行为一个整数n (1<=n<=1000):n代表将要输入的链表元素的个数。(节点编号从1开始)。
接下来有n个数,表示链表节点中的值。
接下来有n个数Ti,Ti表示第i个节点的另一个指针指向。
Ti = 0 表示这个指针为NULL。
- 输出:
-
对应每个测试案例,
输出n行,每行有二个数,第一个代表当前节点值,第二个代表当前节点的特殊指针的值。
- 样例输入:
-
5
1 2 3 4 5
3 5 0 2 0
- 样例输出:
-
1 3
2 5
3 0
4 2
5 0
题意分析:
对于一个含有n个节点的单向链表,指针域中除了next之外,还有一个指向另一个节点或者指向NULL的随机指针。本题的任务是复制一份这样的链表出来。
我的思路,当然是先给节点编号,然后根据编号对应关系重建链表。
其中重要的一步,就是将这些链表节点和1~n的n个整数一一映射起来。这样一来,就能方便地表示随机指针中到底是谁指向谁了。
因为使用了map,所以映射的过程时间复杂度为O(n * log(n))。复制新链表时,也需要查反向映射,仍需要O(n * log(n))的时间。
如果使用适当的hash策略,可以做到接近O(1)的映射时间,时间复杂度也可以降到O(n),但需要额外编码就是了。空间复杂度为O(n)。
最后,不要偷懒直接用数组AC掉(^_^),AC的目的在于学会,而不是通过。
// 688806 zhuli19901106 1524 Accepted 点击此处查看所有case的执行结果 1160KB 3820B 50MS
//
#include <cstdio>
#include <map>
using namespace std; struct RandomListNode {
int label;
RandomListNode *next, *random;
RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
}; // This code segment is copied from my leetcode problem set.
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
int n; if(NULL == head){
return NULL;
} n = ;
RandomListNode *ptr; mri.clear();
mir.clear(); ptr = head;
while(ptr != NULL){
++n;
mri[ptr] = n;
ptr = ptr->next;
} RandomListNode *root = new RandomListNode(), *tail;
ptr = head;
int i = ;
tail = root;
while(ptr != NULL){
++i;
tail->next = new RandomListNode(ptr->label);
tail = tail->next;
mir[i] = tail;
ptr = ptr->next;
} RandomListNode *p1, *p2; p1 = head;
p2 = root->next;
while(p1 != NULL){
if(p1->random != NULL){
p2->random = mir[mri[p1->random]];
}
p1 = p1->next;
p2 = p2->next;
} head = root->next;
delete root;
mir.clear();
mri.clear(); return head;
} RandomListNode *deleteList(RandomListNode *head) {
RandomListNode *ptr1, *ptr2; if (NULL == head) {
return NULL;
} ptr1 = head;
while (ptr1 != NULL) {
ptr2 = ptr1->next;
delete ptr1;
ptr1 = ptr2;
} return NULL;
}
private:
map<RandomListNode *, int> mri;
map<int, RandomListNode *> mir;
}; int main()
{
map<RandomListNode *, int> mri;
map<int, RandomListNode *> mir;
int n, i;
int label;
RandomListNode *head1, *head2, *tail, *ptr;
Solution solution; while (scanf("%d", &n) == ) {
mri.clear();
mir.clear();
head1 = head2 = tail = NULL;
for (i = ; i <= n; ++i) {
scanf("%d", &label);
if (tail == NULL) {
head1 = tail = new RandomListNode(label);
} else {
tail->next = new RandomListNode(label);
tail = tail->next;
}
mri[tail] = i;
mir[i] = tail;
} for (i = ; i <= n; ++i) {
scanf("%d", &label);
if (label > ) {
ptr = mir[i];
ptr->random = mir[label];
}
} head2 = solution.copyRandomList(head1);
ptr = head2;
while (ptr != NULL) {
printf("%d ", ptr->label);
if (ptr->random != NULL) {
printf("%d\n", ptr->random->label);
} else {
printf("0\n");
}
ptr = ptr->next;
} head1 = solution.deleteList(head1);
head2 = solution.deleteList(head2);
} return ;
}
/*
// 688773 zhuli19901106 1524 Accepted 点击此处查看所有case的执行结果 1024KB 544B 40MS
// 201402012022
#include <cstdio>
#include <vector>
using namespace std; int main()
{
vector<int> va, vb;
int n, i;
int a, b; while (scanf("%d", &n) == 1) {
va.clear();
vb.clear();
va.push_back(0);
vb.push_back(0);
for (i = 1; i <= n; ++i) {
scanf("%d", &a);
va.push_back(a);
}
for (i = 1; i <= n; ++i) {
scanf("%d", &b);
vb.push_back(b);
}
for (i = 1; i <= n; ++i) {
printf("%d %d\n", va[i], va[vb[i]]);
}
} return 0;
}
*/
剑指Offer - 九度1524 - 复杂链表的复制的更多相关文章
- 剑指Offer - 九度1518 - 反转链表
剑指Offer - 九度1518 - 反转链表2013-11-30 03:09 题目描述: 输入一个链表,反转链表后,输出链表的所有元素.(hint : 请务必使用链表) 输入: 输入可能包含多个测试 ...
- 剑指Offer - 九度1519 - 合并两个排序的链表
剑指Offer - 九度1519 - 合并两个排序的链表2013-11-30 22:04 题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则.(hi ...
- 剑指Offer - 九度1517 - 链表中倒数第k个结点
剑指Offer - 九度1517 - 链表中倒数第k个结点2013-11-30 02:57 题目描述: 输入一个链表,输出该链表中倒数第k个结点.(hint: 请务必使用链表.) 输入: 输入可能包含 ...
- 剑指Offer - 九度1511 - 从尾到头打印链表
剑指Offer - 九度1511 - 从尾到头打印链表2013-11-29 21:08 题目描述: 输入一个链表,从尾到头打印链表每个节点的值. 输入: 每个输入文件仅包含一组测试样例.每一组测试案例 ...
- 剑指Offer - 九度1505 - 两个链表的第一个公共结点
剑指Offer - 九度1505 - 两个链表的第一个公共结点2013-11-24 20:09 题目描述: 输入两个链表,找出它们的第一个公共结点. 输入: 输入可能包含多个测试样例.对于每个测试案例 ...
- 剑指Offer - 九度1503 - 二叉搜索树与双向链表
剑指Offer - 九度1503 - 二叉搜索树与双向链表2014-02-05 23:39 题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树 ...
- 剑指Offer - 九度1509 - 树中两个结点的最低公共祖先
剑指Offer - 九度1509 - 树中两个结点的最低公共祖先2014-02-07 01:04 题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样 ...
- 剑指Offer - 九度1508 - 把字符串转换成整数
剑指Offer - 九度1508 - 把字符串转换成整数2014-02-06 23:46 题目描述: 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 输入: 输入可能包含多个测试样例 ...
- 剑指Offer - 九度1504 - 把数组排成最小的数
剑指Offer - 九度1504 - 把数组排成最小的数2014-02-06 00:19 题目描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输 ...
随机推荐
- spring-mabatis整合的配置文件
1.spring.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=" ...
- hdu-3015 Disharmony Trees---离散化+两个树状数组
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3015 题目大意: 有一些树,这些树的高度和位置给出.现在高度和位置都按从小到大排序,对应一个新的ra ...
- Android(java)学习笔记70:TabActivity使用
1.首先我们要知道TabActivity是结合TabHost使用的,于是我们自然而然要说明一下TabHost 所谓的TabHost是提供选项卡(Tab页)的窗口视图容器. 此对象包含两个子对象: 一个 ...
- js控制select选中显示不同表单内容
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- JS获取页面传过来的值
利用JS获取页面的传值,此方法只适应Get传值. 获取页面之间的传值,在后台我们很容易获取,那我们在前台只利用JS怎么写呢? 在看代码之前你需要了解的 ① 参考:W3C Location 对象 Loc ...
- Hibernate 异常总结
异常一 异常一 异常描述: Sax解析异常:cvc-复杂的类型,发现了以元素maping开头的无效内容,应该是以 ‘{“http://www.hibernate.org/xsd/orm/cfg“:pr ...
- 你可能不知道的 new.target
new 是构造函数生成实例的命令, ES6为 new 命令引入了 new.target属性.这个属性用于确定构造函数是怎么调用的. 在构造函数中, 如果一个构造函数不是通过 new操作符调用的, ne ...
- python读写dbf数据库
dbf数据库作为一种简单的数据库,曾经广泛使用.现在在金融领域还是有很多的应用之处,工作中遇到此类的问题,在此记录一下. 1. 读取dbf ''' 读取DBF文件 ''' def readDbfFil ...
- Linux文件系统与目录结构
在Linux系统中,目录被组织成一个:单根倒置树结构,文件系统从根目录开始,用/来表示.文件名称区分大小写( 大小写敏感还需要看具体的文件系统格式 ),以.开头的为隐藏文件,路径用/来进行分割(win ...
- Linux进程通信之匿名管道
进程间的通信方式 进程间的通信方式包括,管道.共享内存.信号.信号量.消息队列.套接字. 进程间通信的目的 进程间通信的主要目的是:数据传输.数据共享.事件通知.资源共享.进程控制等. 进程间通信之管 ...