去重合并两个有序链表之直接操作和Set集合操作
两者思路对比:
直接操作:因为传入的是两个有序的链表,所以说我就直接以其中一个链表为基准,与另外一个链表比较,只将比返回值链表的最后一个记录的值大的插入,不将等值的插入,理论时间复杂度为O(n)
Set操作:将所有的节点取出放入TreeSet有序集合中,最后生成一个链表返回,理论时间复杂度为O(2n)
直接操作步骤示意图:
以{1,3,5}{1,2,4,5,5,6}为例
- 先取个返回值链表的表头,并将该链表作为基准链表,比较第一个值小的为基准链表,相同就取第一个
返回值链表:1->null
基准链表:3->5->null
非基准链表:1->2->4->5->5->6->null - 继续下一步后的链表,这一步中,取两个链表中的小值尝试插入,但是发现与返回值链表末端值相同就丢弃
返回值链表:1->null
基准链表:3->5->null
非基准链表:2->4->5->5->6->null - 继续下一步后的链表,这一步中,取两个链表中的小值尝试插入,但是发现与返回值链表末端值不同就插入
返回值链表:1->2->null
基准链表:3->5->null
非基准链表:4->5->5->6->null - 继续下一步后的链表,这一步中,取两个链表中的小值尝试插入,但是发现与返回值链表末端值不同就插入
返回值链表:1->2->3->null
基准链表:5->null
非基准链表:4->5->5->6->null - 继续下一步后的链表,这一步中,取两个链表中的小值尝试插入,但是发现与返回值链表末端值不同就插入
返回值链表:1->2->3->4->null
基准链表:5->null
非基准链表:5->5->6->null - 继续下一步后的链表,这一步中,取两个链表中的小值尝试插入,但是发现与返回值链表末端值不同就插入
返回值链表:1->2->3->4->5->null
基准链表:null
非基准链表:5->5->6->null - 其中一个链表为null之后直接只遍历另外一个链,因为要去重,所以要遍历完,取非基准链表中的一个值尝试插入,但是发现与返回值链表末端值相同就丢弃
返回值链表:1->2->3->4->5->null
基准链表:null
非基准链表:5->6->null - 取非基准链表中的一个值尝试插入,但是发现与返回值链表末端值相同就丢弃
返回值链表:1->2->3->4->5->null
基准链表:null
非基准链表:6->null - 取非基准链表中的一个值尝试插入,但是发现与返回值链表末端值不同就保留,此时两个链表都为null则结束
返回值链表:1->2->3->4->5->6null
基准链表:null
非基准链表:null
对于Set操作的算法则不展开
自己写的比较的算法:
import java.util.*; public class Main { public static void main(String[] args) {
Node headOne = new Node(-1);
Node headTwo = new Node(-1);
Node p1 = headOne;
Node p2 = headTwo;
int[] one = new int[10000];
int[] two = new int[15000];
Random rm = new Random();
for (int i = 0; i < 10000; i++){
one[i] = rm.nextInt(500);
}
for (int i = 0; i < 15000; i++){
two[i] = rm.nextInt(500);
}
Arrays.sort(one);
Arrays.sort(two);
for (int i = 0; i < one.length; i++){
Node node = new Node(one[i]);
p1.next = node;
p1 = p1.next;
}
for (int i = 0; i < two.length; i++){
Node node = new Node(two[i]);
p2.next = node;
p2 = p2.next;
} long start = System.nanoTime();
Node re = change(headOne.next, headTwo.next);
long end = System.nanoTime(); System.out.println("直接操作:" + (end - start) + "ns"); start = System.nanoTime();
Node reSet = changeSet(headOne.next, headTwo.next);
end = System.nanoTime();
System.out.println("Set时间: " + (end - start) + "ns");
} private static Node change(Node headOne, Node headTwo){
//空值判断
if (headTwo == null){
return headOne;
}
if (headOne == null){
return headTwo;
} //返回首元素较小的头结点, 先取一个节点为基准
Node reHead = headOne.data <= headTwo.data? headOne: headTwo;
Node p2 = headOne.data >= headTwo.data? headTwo: headOne; //另一条链
Node pre = reHead; //上一个节点
Node p1 = reHead.next; //当前链 while(p1 != null && p2 != null){
if(p1.data <= p2.data){
if (p1.data == p2.data){
p2 = p2.next;
}
if (p1.data != pre.data){
pre = pre.next;
p1 = p1.next;
}else{
pre.next = p1.next; //跳过该相同节点
p1 = p1.next;
}
}else{
if (p2.data != pre.data){
pre.next = p2;
p2 = p2.next;
pre = pre.next;
pre.next = p1;
}else {
p2 = p2.next;
}
}
} Node now = p1 != null? p1: p2;
pre.next = now;
while(now!= null){
if (pre.data == now.data){
now = now.next;
pre.next = now;
}else{
pre = pre.next;
now = now.next;
}
}
return reHead;
} private static Node changeSet(Node headOne, Node headTwo){
Node re = new Node(-1);
Node head = re;
TreeSet<Node> s = new TreeSet<>();
while(headOne != null){
s.add(headOne);
headOne = headOne.next;
}
while(headTwo != null){
s.add(headTwo);
headTwo = headTwo.next;
}
Iterator iterator = s.iterator();
while (iterator.hasNext()){
Node p = (Node) iterator.next();
Node tmp = new Node(p.data);
head.next = tmp;
head = head.next;
}
return re.next;
}
} class Node implements Comparable{
int data;
Node next; public Node(int data){
this.data = data;
} @Override
public int compareTo(Object o) {
Node t = (Node)o;
if (this.data > t.data){
return 1;
}else if (this.data == t.data){
return 0;
}else {
return -1;
}
}
}
实现代码
然后运行的时间截图:
如有错误和不足,望指正
千里之行,始于足下
去重合并两个有序链表之直接操作和Set集合操作的更多相关文章
- 【LeetCode题解】21_合并两个有序链表
目录 21_合并两个有序链表 描述 解法一:迭代 思路 Java 实现 Python 实现 解法二:递归 思路 Java 实现 Python 实现 21_合并两个有序链表 描述 将两个有序链表合并为一 ...
- leetcode 21 Merge Two Sorted Lists 合并两个有序链表
描述: 合并两个有序链表. 解决: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { if (!l1) return l2; if (!l2) ...
- Leecode刷题之旅-C语言/python-21.合并两个有序链表
/* * @lc app=leetcode.cn id=21 lang=c * * [21] 合并两个有序链表 * * https://leetcode-cn.com/problems/merge-t ...
- LeetCode初级算法--链表02:合并两个有序链表
LeetCode初级算法--链表02:合并两个有序链表 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn. ...
- <每日 1 OJ> -LeetCode 21. 合并两个有序链表
题目: 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4输出:1->1-> ...
- 算法练习之合并两个有序链表, 删除排序数组中的重复项,移除元素,实现strStr(),搜索插入位置,无重复字符的最长子串
最近在学习java,但是对于数据操作那部分还是不熟悉 因此决定找几个简单的算法写,用php和java分别实现 1.合并两个有序链表 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两 ...
- LeetCode 21. 合并两个有序链表(Merge Two Sorted Lists)
21. 合并两个有序链表 21. Merge Two Sorted Lists 题目描述 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. LeetCode ...
- leecode刷题(23)-- 合并两个有序链表
leecode刷题(23)-- 合并两个有序链表 合并两个有序链表 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2-> ...
- LeetCode_21.合并两个有序链表
LeetCode_21 LeetCode-21.合并两个有序链表 将两个有序链表合并为一个新的有序链表并返回. 新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2-> ...
随机推荐
- Java中...的作用
Java中...的作用,代表接收若干个相同类型的参数 public void testFunction(int...arr){ //接收若干个int类型的参数 for (int i:ar ...
- Spring项目集成ShiroFilter简单实现权限管理
Shiros是我们开发中常用的用来实现权限控制的一种工具包,它主要有认证.授权.加密.会话管理.与Web集成.缓存等功能.我是从事javaweb工作的,我就经常遇到需要实现权限控制的项目,之前我们都是 ...
- 深入理解 linux磁盘顺序写、随机写
一.前言 ● 随机写会导致磁头不停地换道,造成效率的极大降低:顺序写磁头几乎不用换道,或者换道的时间很短 ● 本文来讨论一下两者具体的差别以及相应的内核调用 二.环境准备 组件 版本 OS Ubunt ...
- Mongodb最基础入门教程
Mongodb最基础入门教程 如果想了解一下redis的入门教程,可以去看一下我的上一篇博客 Mongodb的安装大家可以参考一下其他博主的博客,这里我就不做介绍了.不过值得注意的是,在Linux ...
- activemq的下载与安装
一.介绍 Apache ActiveMQ™是最流行的开源,多协议,基于Java的消息服务器.它支持行业标准协议,因此用户可以通过广泛的语言和平台获得客户选择的好处.可以使用C,C ++,Python, ...
- C#数据结构_树
树的定义是递归的,用树来定义树.因此,树(以及二叉 树)的许多算法都使用了递归. 结点(Node):表示树中的数据元素. 结点的度(Degree of Node):结点所拥有的子树的个数. 树的度(D ...
- springBoot日志框架自动配置与原理
1.日志框架 小张:开发一个大型系统: 1.System.out.println(""):将关键数据打印在控制台:去掉?写在一个文件? 2.框架来记录系统的一些运行时信息: ...
- 【原创】Linux cpufreq framework
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...
- linux命令名 用法及参数 功能注解
命令名 用法及参数 功能注解 1 文件管理 # ls ls -a 列出当前目录下的所有文件,包括以.头的隐含文件 文件管理 # l ...
- 2019nc#4
题号 标题 已通过代码 题解 通过率 团队的状态 A meeting 点击查看 树直径 604/2055 B xor 点击查看 线段树维护线性基交 81/861 未通过 C sequence 点击 ...