剑指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 题目描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输 ...
随机推荐
- April 6 2017 Week 14 Thursday
If you smile when no one else is around, you really mean it. 独处时的微笑,才是发自内心的. Recently I found I seld ...
- spring boot1.5.6 测试类1
package com.example.demo; import org.junit.Before;import org.junit.Test; import org.junit.runner.Run ...
- Java中阻塞队列的使用
http://blog.csdn.net/qq_35101189/article/details/56008342 在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如 ...
- OpenFire通过User Service管理用户
安装OpenFire服务器略去 1.安装User Service插件: 在管理控制平台找到选项卡“插件”,里边有我们需要安装的一个User Service插件,如果安装过了会显示已经安装的哪些插件,没 ...
- typeid操作符
typeid() operator返回type_info,返回值不可拷贝.不可赋值 // Illustrates the typeid operator. #include <iostream& ...
- Informatica 简单使用
1. Informatica简介 ① Repository manager 主要用来维护资料库的目录,对象,建完对象可以创建demo的folder. ② Administration Console是 ...
- JQuery 解决按钮上的倒计时问题
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...
- java斗地主扑克 扑克牌 洗牌 发牌 Collection 集合练习
package com.swift.poker; import java.util.ArrayList; import java.util.Collections; /*训练考核知识点:Collect ...
- Mac openssl 和curl源码编译
1.先编译openssl, 下载源码后解压,终端进入源码目录,输入命令配置编译环境:./Configure darwin64-x86_64-cc 等待配置完成后,输入make 和make insta ...
- finddler的安装与设置
这是抓取手机包的设置 过滤 新安装的,可能还需要证书问题