剑指offer面试题26-复杂链表的复制
题目:
请实现函数ComplexListNode* Clone(ComplexListNode* pHead)。复制一个复杂链表。
在复杂链表中。每个节点除了一个m_pNext指针指向下一个节点外,另一个m_pSibling指向链表中的随意节点或者NULL,节点的定义例如以下:
package com.aii.algorithm; public class Node {
int value;
Node next;
Node sibling; public Node(int value) {
this.value = value;
} public Node() {
} }
一.思路:
能够分两步来实现:
1.先复制链表。sibling就用旧链表的,照搬。
2.再复制silbing
怎么复制sibling,这个借助一个HashMap(在O(1)时间内可以找到),将Node与其复制的Node'的映射关系存到HashMap中。
在第二步改动sibling的时候,依据原先sibling的Node去Map中找,找到相应的那个就是他应该指向的那个。
代码实现:
package com.aii.algorithm; import java.util.HashMap;
import java.util.Map; public class CloneNodes {
// 第一步:复制链表
// 第二步:复制sibing的指针位置
public Node clone(Node head) {
Map<Node, Node> map = new HashMap<Node, Node>(); // copy linkedlist
Node newHead = cloneNode(head, map); // copy silbing points
Node tmpNewHead = newHead;
while (tmpNewHead != null) {
// get from mapping
tmpNewHead.sibling = map.get(tmpNewHead.sibling);
tmpNewHead = tmpNewHead.next;
}
return newHead;
} // 1.递归克隆
// 2.同一时候将Node,以及Node'的映射关系放入到map中,方便map.next查找
private Node cloneNode(Node head, Map<Node, Node> map) {
if (head == null) {
return null;
}
Node node = new Node();
node.next = cloneNode(head.next, map);
node.sibling = head.sibling;
map.put(head, node);
node.value = head.value;
return node;
}
}
二、
这里借助了HashMap
假设不借助HashMap,又要在O(n)时间完毕?
不使用Map,在改动sibling的时候。麻烦之处在哪?
在于找不到新复制的节点。
下图:
比方说要在A'位置找A'的silbing,那就要A'与A一起往前走,直到某个节点Node==A.sibling这个时候相应的Node'也应该是A'.silbing。
可是这种时间复杂度为O(n*n)
这里有一个好的办法:
分三步走:
1.将新复制的链表穿插到旧的链表中
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
2.这样子就行依据左右位置的旧的节点找到sibling位置了
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
3.还原。
代码实现:
package com.aii.algorithm; public class CloneNodes2 { // 1.将新的节点插入到链表原始节点的后面
// 2.将新的节点的sibling的指针给赋值。是原先值的next
// 3.再将新的节点链表从中独立出来
public Node clone(Node head) {
Node tmp = head;
// 1.第一步。插入新的节点
while (tmp != null) {
Node next = tmp.next;
Node node = new Node();
node.value = tmp.value;
node.next = tmp.next;
tmp.next = node;
//
tmp = next;
} // 2.第二步,设置sibling
int count = 0;
tmp = head;
Node nodeNext = null;
while (tmp != null) {
if (count++ % 2 == 0) {
nodeNext = tmp.next;
} else {
tmp.next = nodeNext.next;
}
tmp = tmp.next;
} // 3.第三步。将新的链表独立出来,而且还原原先的链表
tmp = head;
Node newHead = null;
count = 0;
while (tmp != null) {
tmp.next = tmp.next.next;
newHead = tmp.next; tmp = tmp.next;
} return newHead;
}
}
三、測试用例:
因为引用关系比較复杂,toStringeasy引发空指针。这里附上測试用例:
package com.aii.algorithm; import org.junit.Before;
import org.junit.Test; public class CloneNodes2Test {
private Node head = new Node('a'); @Before
public void init() {
Node n2 = new Node('b');
Node n3 = new Node('c');
Node n4 = new Node('d');
Node n5 = new Node('e'); head.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5; //
head.sibling = n3;
n2.sibling = n5;
n3.sibling = n2;
} @Test
public void test() {
printNode(head);
Node node = new CloneNodes().clone(head);
System.out.println("-----");
printNode(node);
System.out.println("-----");
printNode(head);
} private void printNode(Node node) {
Node tmp = node;
while (tmp != null) {
int sibling = -1;
if (tmp.sibling != null) {
sibling = tmp.sibling.value;
}
int next = -1;
if (tmp.next != null) {
next = tmp.next.value;
}
System.out.print("value:" + (char) tmp.value);
System.out.print("\tsibling:" + (char) sibling);
System.out.println("\tnext:" + (char) next);
tmp = tmp.next;
}
}
}
结果:
value:a sibling:cnext:b
value:b sibling:enext:c
value:c sibling:bnext:d
value:d sibling:?next:e
value:e sibling:?next:?
-----
value:a sibling:cnext:b
value:b sibling:enext:c
value:c sibling:bnext:d
value:d sibling:?next:e
value:e sibling:?next:?
-----
value:a sibling:cnext:b
value:b sibling:enext:c
value:c sibling:bnext:d
value:d sibling:?next:e
value:e sibling:?
next:?
剑指offer面试题26-复杂链表的复制的更多相关文章
- 剑指offer 面试题35.复杂链表的复制
时间O(N),空间O(N) /* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomList ...
- 剑指Offer - 九度1524 - 复杂链表的复制
剑指Offer - 九度1524 - 复杂链表的复制2014-02-07 01:30 题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点 ...
- 剑指Offer面试题:14.链表的倒数第k个节点
PS:这是一道出境率极高的题目,记得去年参加校园招聘时我看到了3次,但是每次写的都不完善. 一.题目:链表的倒数第k个节点 题目:输入一个链表,输出该链表中倒数第k个结点.为了符合大多数人的习惯,本题 ...
- 剑指offer面试题26:复杂链表的复制
题目:请实现一个函数,复制一个复杂链表. 在复杂链表中,每个结点除了有一个next指针指向下一个结点外,还有一个sibling指针指向链表中的任意结点或者nulL 直观解法: 1.遍历链表,复制链表节 ...
- 剑指Offer:面试题26——复制复杂的链表(java实现)
问题描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点). 思路1: 1.先复制链表节点,并用next链接起来. 2.然后对每一个结点去修改 ...
- 剑指Offer:面试题16——反转链表(java实现)
问题描述 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后的链表的头结点.链表结点如下: public class ListNode { int val; ListNode next = n ...
- 【剑指offer 面试题15】链表中倒数第K个结点
思路: 定义两个指针同时指向head,第一个指针先走K-1步,随后二个指针同时移动,当第一个指针到末尾处时,第二个指针所指向的即为倒数第K个结点. #include <iostream> ...
- 剑指offer面试题15:链表中倒数第K个节点
题目:输入一个链表,输出该链表的倒数第K个节点.为了符合大多数人的习惯,本题从1开始计数,即链表尾节点是倒数第一个节点. 解题思路: 解法一:一般情况下,单向链表无法从后一个节点获取到它前面的节点,可 ...
- 剑指offer——面试题23:链表中环的入口节点
函数: ListNode* MeetingNode(ListNode* pHead) { if(pHead==nullptr) return nullptr; ListNode* quickNode= ...
随机推荐
- Linux 程序设计学习笔记----Linux下文件类型和属性管理
转载请注明出处:http://blog.csdn.net/suool/article/details/38318225 部分内容整理自网络,在此感谢各位大神. Linux文件类型和权限 数据表示 文件 ...
- 2014.08.04,读书,读书笔记-《Matlab概率与数理统计分析》-第1章 MATLAB的数据基础
第1章 MATLAB数据基础 虽然一直间或使用MATLAB,但从来没有系统的学习过,现在开始也不晚.先对几个重点或者平时忽略的要点做下笔记. %后的所有文字为注释,多条命令可以放在一行,但要用逗号或分 ...
- 杂项-公司:YKK
ylbtech-杂项-公司:YKK YKK的全称为Yoshida Kogyo Kabushikigaisha.YKK是拉链行业的鼻祖,代表着行业标准,因为采用日本精确的工艺,原料和管理方法,YKK价格 ...
- Python学习历程之模块浅识
# =============================操作系统模块=======================# import os# 待续# ======================= ...
- Python学习历程之面对对象浅识
# ===============================封装====================================# class Bar:# def __init__(se ...
- Jquery validform
一.validform是什么? validform是一款智能的表单验证js插件,它是基于jQuery库与css,我们只需要把表单对象放入, 就可以对整个表 ...
- art-template模板渲染及其过滤器
原生语法 使用原生语法,需要导入template-native.js文件.在HTML中定义模板,注意模板的位置,不要放到被渲染区域,防止模板丢失. <script id="tpl&qu ...
- 《鸟哥的Linux私房菜》笔记——04. 简单命令行
键入命令 [dmtsai@study ~]$ command [-options] parameter1 parameter2 ... 指令 選項 參數(1) 參數(2) 注意:有时也可以使用 + 放 ...
- Unity5.X 编辑器介绍
导航窗口中有一个 Add Asset Package 按钮,可以导入一些官方的资源包,例如Characters角色控制器 Windows → Layouts 可以更换窗口的摆放 常见视图 ...
- xgboost学习
1.原理 https://www.cnblogs.com/zhouxiaohui888/p/6008368.html 2.实战 xgboost中比较重要的参数介绍: (1)学习率:learning r ...