每日一题 为了工作 2020 0325 第二十三题

/**
*
* 问题: 复制含有随机指针节点的链表
*
* 分析:
* 给定一个由Node节点类型组成的无环单链表的头节点head, 请实现一个函数完成这
* 个链表中所有结构的复制, 并返回复制的新链表的头节点。例如: 链表1->2->3->null,
* 假设1的 rand指针指向3, 2的 rand指针指向 null, 3的 rand指针指向1。复制后的链
* 表应该也是这种结构, 比如, 1‘->2‘->3‘->null, 1‘的 rand指针指向3‘,2‘的 rand
* 指针指向 null, 3‘的 rand指针指向1‘, 最后返回1‘。
*
* 解答:
*
*1.首先从左到右遍历链表, 对每个节点都复制生成相应的副本节点, 然后将对应关系放入哈希
*表 map中。例如, 链表1->2->3->null, 遍历1、2、3时依次生成1‘、2‘、3‘。 最后将
*对应关系放入map中:
*
*2.再从左到右遍历链表, 此时就可以设置每一个副本节点的 next和 rand指针。例如原链表
*1->2->3->null, 假设1的 rand指针指向3, 2的 rand指针指向null, 3的rand指针
*指向1。遍历到节点1时, 可以从map中得到节点1的副本节点1‘, 节点1的next指向节点2,
*所以从map中得到节点2的副本节点2‘, 然后令1‘.next=2‘, 副本节点1‘的next指针就
*设置好了。同时节点1的rand指向节点3, 所以从map中得到节点3的副本节点3‘, 然后令
*1‘.rand=3‘, 副本节点1的rand指针也设置好了。以这种方式可以设置每一个副本节点的
*next与rand指针。
*
*3.将 1‘节点作为结果返回即可。
*
*哈希表增删改查的操作时间复杂度都是0(1), 普通方法一共只遍历链表两遍, 所以普通解法的
*时间复杂度为O(N), 因为使用了哈希表来保存原节点与副本节点的对应关系, 所以额外空间复杂度为O(N)。
*
* @author 雪瞳
*
*/

*代码

public class Node {
	public int value;
	public Node next;
	public Node rand;
	public Node(int data) {
		this.value=data;
	}
}

  

import java.util.HashMap;
import java.util.Map;

public class CopyListWithRand {

	public Node copyList(Node head) {

		Map<Node, Node> map = new HashMap<Node, Node>();
		Node current = head;
		//复制链表
		while(current!=null) {
			map.put(current, new Node(current.value));
			current=current.next;
		}
		//更新指针
		current = head;
		while(current!=null){
			map.get(current).next=map.get(current.next);
			map.get(current).rand=map.get(current.rand);
			current=current.next;
		}

		return map.get(head);
	}
}

  

public class TestCopyListWithRand {

	public static void main(String[] args) {
		TestCopyListWithRand test = new TestCopyListWithRand();
		CopyListWithRand copy = new CopyListWithRand();

		Node head1 = new Node(1);
		Node head2 = new Node(2);
		Node head3 = new Node(3);
		Node head4 = new Node(4);
		Node copyHead = null;

		//为方便观察效果将head1都设为头节点
		head1.next=head2;
		head2.next=head3;
		head3.next=head4;

		head1.rand=head3;
		head3.rand=head4;
		head4.rand=head2;

		System.out.println("初始状态...");
		test.showByTip(head1, "next");
		test.showByTip(head1, "rand");

		copyHead = copy.copyList(head1);

		System.out.println("复制后状态...");
		test.showByTip(copyHead, "next");
		test.showByTip(copyHead, "rand");

	}
	public void showByTip(Node head ,String tip) {
		Node current = null;
		System.out.println("链表内的值按照"+tip+"顺序显示如下:...");
		if(tip.equals("next")) {
			current=head;
			while(current!=null) {
				System.out.print(current.value+"\t");
				current=current.next;
			}
		}else if(tip.equals("rand")) {
			current=head;
			while(current!=null) {
				System.out.print(current.value+"\t");
				current=current.rand;
			}
		}
		System.out.println();
	}
}

  

*运行结果

原文地址:https://www.cnblogs.com/walxt/p/12565488.html

时间: 2024-10-06 00:53:57

每日一题 为了工作 2020 0325 第二十三题的相关文章

每日一题 为了工作 2020 0322 第二十题

/** * 问题: 判断一个链表是否为回文结构 * 给定一个链表的头节点head, 请判断该链表是否为回文结构. * * 例如: * 1->2->1, 返回 true. * 1->2->2-> 1, 返回 true . * 15->6-> 15, 返回 true. * 1->2->3, 返回 false. * * 解答: * 利用栈结构即可.从左到右遍历链表, 遍历的过程中把每个节点依次压入栈中. * 因为栈是先进后出的, 所以在遍历完成后, 从栈顶到

每日一题 为了工作 2020 0323 第二十一题

/** * 题目:将单向链表按某值划分成左边小.中间相等.右边大的形式 * * 要求: * 给定一个单向链表的头节点 head, 节点的值类型是整型, 再给定一个整数 privot.实现 *一个调整链表的函数, 将链表调整为左部分都是值小于privot的节点, 中间部分都是值等于privot *的节点, 右部分都是值大于privot的节点.除这个要求外, 对调整后的节点顺序没有更多的要求. *例如: 链表 9->0->4->5->1, privot=3.调整后链表可以是1->

每日一题 为了工作 2020 0304 第二题

/** * 题目: * 编写一个类,用两个栈实现队列,支持队列的基本操作(add.poll.peek) * 分析: * 栈的特点是先进后出,而队列的特点是先进先出,我们可以用两个栈正好能把顺序 * 反过来实现类似队列的操作. * 具体实现是一个栈作为压入栈,在压入数据时只往这个栈中压入,记为stackPush, * 另一个栈只作为弹出栈,在弹出数据时只从这个栈弹出,记为stackPop. * 因为数据压入栈的时候,顺序是先进后出的,那么只要把stackPush的数据在压入 * stackPop中

每日一题 为了工作 2020 0305 第三题

/** * 问题: * 如何仅适用递归函数和栈操作逆序一个栈 * 一个栈依次压入1.2.3.4.5,那么从栈顶到栈底分别为5.4.3.2.1.将这个栈转置后, * 从栈顶到栈底为5.4.3.2.1,也就是实现了栈中元素的逆序,但是只可以通过递归函数来实现. * 分析: * 本题目考验查找操作和递归函数的设计,我们需要设计出两个递归函数. * 函数一:将栈stack中的栈底元素返回并移除 * getAndRemoveLastElement() * 函数二:逆序一个栈 * @author 雪瞳 *

每日一题 为了工作 2020 03019 第十七题

/** * 问题:反转双向链表 * * 要求: * 如果链表长度为 N,时间复杂度为O(N),额外的空间复杂度为O(1). * * @author 雪瞳 * */ public class Node<T>{ public T value; public Node next; public Node last; public Node(T data){ this.value =data; } } public class reverseList { private Node current =

经典算法题每日演练——第二十三题 鸡尾酒排序

原文:经典算法题每日演练--第二十三题 鸡尾酒排序 这篇我们继续扯淡一下鸡尾酒排序,为了知道为啥取名为鸡尾酒,特意看了下百科,见框框的话,也只能勉强这么说了. 要是文艺点的话,可以说是搅拌排序,通俗易懂点的话,就叫“双向冒泡排序”,我想作为码农的话,不可能不知道冒泡排序, 冒泡是一个单向的从小到大或者从大到小的交换排序,而鸡尾酒排序是双向的,从一端进行从小到大排序,从另一端进行从大 到小排序. 从图中可以看到,第一次正向比较,我们找到了最大值9. 第一次反向比较,我们找到了最小值1. 第二次正向

每日一题 为了工作 2020 0303 第一题

Java 栈的相关操作 题目 : * 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作 * 要求 : * 1.pop.push.getMin操作的时间复杂度都是O(1). * 2.设计栈类型可以使用现成的栈结构. * 首先明确Java栈的相关操作函数 Stack stack = new Stack();//实例化栈对象 * 进栈操作 stack.push(“Object”);//返回的是入栈的内容 stack.add("Object");//返回的是true或

每日一题 为了工作 2020 0317 第十五题

/** * 题目:删除链表的a/b处节点 * 给定链表的头节点 head.整数 a和 b, 实现删除位于 a/b处节点的函数. * * 例如: * 链表: 1->2->3->4->5, 假设a/b的值为r. * 如果r等于0, 不删除任何节点: * 如果r在区间(0, 1/5]上, 删除节点1; * 如果r在区间(1/5, 2/5]上, 删除节点2; * 如果r在区间(2/5, 3/5]上, 删除节点3; * 如果r在区间(3/5, 4/5]上, 删除节点4; * 如果r在区间(4

每日一题 为了工作 2020 0405 第三十四题

/** * 问题: 向有序的环形单链表中插入新节点 * 一个环形单链表从头节点 head开始不降序, 同时由最后的节点指回头节点.给定这样 * 一个环形单链表的头节点 head和一个整数 num, 请生成节点值为 num的新节点,并插入到 * 这个环形链表中, 保证调整后的链表依然有序. * * 解题: * 1. 生成节点值为 num的新节点, 记为 node. * 2. 如果链表为空, 让 node自己组成环形链表, 然后直接返回node. * 3. 如果链表不为空, 令变量 pre=head