剑指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. 使用SSH密钥方式登录ubuntu Linux,指令(ssh-keygen 和 ssh-copy-id)

    实验目的 从myVM1(本地主机)上登录myVM2(远程主机).采用密钥方式,不输入密码. 测试环境 主机:window7 sp1 64位 专业版 虚拟机:VMware workstation 12 ...

  2. navicat for mysql注册码:NAVN-LNXG-XHHX-5NOO

    名.组织可以为空或任意填写. 摘自: navicat for mysql10.0.0.0注册码中“名”.“组织”...._百度知道

  3. 【2017-07-04】Qt信号与槽深入理解之一:信号与槽的连接方式

    今天是个好日子,嗯. 信号槽机制是Qt的特色功能之一,类似于windows中的消息机制,在不同的类对象间传递消息时我们经常使用信号槽机制,然而很多时候都没有去关注connect()函数到底有几种重载的 ...

  4. java多线程安全

    class Ticket implements Runnable { public int sum=10; public void run() { while(true) { if(sum>0) ...

  5. Selenium入门18 断言

    自动化测试需对比实际结果与预期结果,给出测试结论. 1 条件判断 if ...else... 2 assert ... #coding:utf-8 #断言 from selenium import w ...

  6. 计算最大矩形面积,POJ(2082)

    题目链接:http://poj.org/problem?id=2082 把矩形按照高度一次递增的循序排列,当违反这一规则的时候,更新ans,用新的data替换之前的矩形.然后最后扫一遍. #inclu ...

  7. http长链接

    之前说过http的请求是再tcp连接上面进行发送的,那么tcp连接就分为长连接 和 短连接这样的概念,那么什么是长链接呢?http请求发送的时候要先去创建一个tcp的连接,然后在tcp的连接上面发送h ...

  8. python 添加 threadpool

    操作系统: Ubuntu 10.04 python安装依赖的软件包: python 出现 ImportError: No module named ** 我这里出现了: ImportError: No ...

  9. python-列表常用功能介绍

    一.列表(list) 1.定义列表 names = [] #定义空列表 names = ['a','b','c'] #定义非空列表 2.访问列表中元素 >>> names = ['a ...

  10. Ext4.2 select 和 query 区别与联系

    Ext.query和Ext.select的作用是一致的,同是根据CSS选择符查找出一个或多个元素.区别在于返回类型上.分别是:query方法返回的是JavaScript标准的数组类型:select方法 ...