剑指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 - 复杂链表的复制的更多相关文章

  1. 剑指Offer - 九度1518 - 反转链表

    剑指Offer - 九度1518 - 反转链表2013-11-30 03:09 题目描述: 输入一个链表,反转链表后,输出链表的所有元素.(hint : 请务必使用链表) 输入: 输入可能包含多个测试 ...

  2. 剑指Offer - 九度1519 - 合并两个排序的链表

    剑指Offer - 九度1519 - 合并两个排序的链表2013-11-30 22:04 题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则.(hi ...

  3. 剑指Offer - 九度1517 - 链表中倒数第k个结点

    剑指Offer - 九度1517 - 链表中倒数第k个结点2013-11-30 02:57 题目描述: 输入一个链表,输出该链表中倒数第k个结点.(hint: 请务必使用链表.) 输入: 输入可能包含 ...

  4. 剑指Offer - 九度1511 - 从尾到头打印链表

    剑指Offer - 九度1511 - 从尾到头打印链表2013-11-29 21:08 题目描述: 输入一个链表,从尾到头打印链表每个节点的值. 输入: 每个输入文件仅包含一组测试样例.每一组测试案例 ...

  5. 剑指Offer - 九度1505 - 两个链表的第一个公共结点

    剑指Offer - 九度1505 - 两个链表的第一个公共结点2013-11-24 20:09 题目描述: 输入两个链表,找出它们的第一个公共结点. 输入: 输入可能包含多个测试样例.对于每个测试案例 ...

  6. 剑指Offer - 九度1503 - 二叉搜索树与双向链表

    剑指Offer - 九度1503 - 二叉搜索树与双向链表2014-02-05 23:39 题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树 ...

  7. 剑指Offer - 九度1509 - 树中两个结点的最低公共祖先

    剑指Offer - 九度1509 - 树中两个结点的最低公共祖先2014-02-07 01:04 题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样 ...

  8. 剑指Offer - 九度1508 - 把字符串转换成整数

    剑指Offer - 九度1508 - 把字符串转换成整数2014-02-06 23:46 题目描述: 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 输入: 输入可能包含多个测试样例 ...

  9. 剑指Offer - 九度1504 - 把数组排成最小的数

    剑指Offer - 九度1504 - 把数组排成最小的数2014-02-06 00:19 题目描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输 ...

随机推荐

  1. Windows计算下载文件的SHA256 MD5 SHA1

    引用自 http://blog.163.com/licanli2082@126/blog/static/35748686201284611330/ certutil -hashfile yourfil ...

  2. class类重定义

    C++项目中如果一个头文件被多个文件包含,#include"xxx.h",将可能导致头文件里面定义的类被多次编译,解决方法是加编译指示: #pragma once //告诉编译器只 ...

  3. nodejs封装的webget webpost方法

    在我之前的项目中,经常用到Nodejs通过post\get方法访问其它网站.webapi.下面是我封装的 Get.Post方法,很适合在一些web字符串收发场景使用(暂不支持文件.二进制流等传输). ...

  4. Linux 源码安装MariaDB 10.0.16

    cmake软件   tar -zxvf cmake-2.8.8.tar.gz cd cmake-2.8.8 ./bootstrap make && make install     依 ...

  5. python Unittest+excel+ddt数据驱动测试

    #!user/bin/env python # coding=utf- # @Author : Dang # @Time : // : # @Email : @qq.com # @File : # @ ...

  6. Ubuntu下几种常用的文本编辑器

    常见的基于控制台的文本编辑器有以下几种: emacs           综合性的GNU emacs 编辑环境 nano              一个类似于经典的pico的文本编辑器,内置了一个pi ...

  7. 自学youku_web

    仿youku架构 数据库设计 管理员 注册 登录 上传视频 删除视频 发布公告 普通用户 注册 登录 充会员 查看视频 下载免费视频 下载收费视频 查看观影记录 查看公告 思路 class Field ...

  8. MySQL常见错误分析与解决方法总结

    MySQL常见错误分析与解决方法总结 一.Can't connect to MySQL server on 'localhost' (10061)翻译:不能连接到 localhost 上的mysql分 ...

  9. 3、SpringBoot------邮件发送(1)

    开发工具:STS 代码下载链接:https://github.com/theIndoorTrain/Springboot/tree/8878e8e89ce01ceb967ef8c1193ac740a6 ...

  10. POJ2154 Color(Polya定理)

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11654   Accepted: 3756 Description Bead ...