去重合并两个有序链表之直接操作和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-> ...
随机推荐
- dubbokeeper-moniter部署指南
moniter在整个dubbo架构中的角色: 使用的1.0.1版本: ## 1.0.1版本变动内容 dubbokeeper在1.0.1版本对监控数据存储模块抽离出来,做为单独的应用部署,而不是和1.0 ...
- 史上最全面的SignalR系列教程-2、SignalR 实现推送功能-永久连接类实现方式
1.概述 通过上篇史上最全面的SignalR系列教程-1.认识SignalR文章的介绍,我们对SignalR技术已经有了一个全面的了解.本篇开始就通过SignalR的典型应用的实现方式做介绍,例子虽然 ...
- Simple Windows Service in C++
本文是来自CodeProject中的一篇名为Simple Windows Service in C++的译文,原文地址为:https://www.codeproject.com/Articles/49 ...
- 配置Oracle透明网关用以连接 SQLServer经验总结
一.情景介绍 业务中设计两个不同的系统,系统1和系统2,两个系统分别使用的是Oracle和SQLServer数据库.现需要在系统1的数据库中直接查询系统2数据库的数据.即在Oracle中执行SQL ...
- Python模块——HashLib(摘要算法)与base64
摘要算法(hashlib) Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等. 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度 ...
- Delegate,Block,Notification, KVC,KVO,Target-Action
Target-Action: 目标-动作机制,所有的UIControl及子类都是这个机制:原理:在对象产生某个事件的特定时刻,给一个对象发送一个消息:类内部target去执行action方法 Dele ...
- 【JVM从小白学成大佬】开篇
JVM的重要性毋庸置疑,可以毫不夸张的说Java虚拟机是整个Java平台的基石. JVM方面的知识,也一直是BAT等大厂面试考核的重点.特别是JVM调优,故障排查性能调优,你知道该从哪些方面入手吗? ...
- C#数据结构_查找
查找:静态查找和动态查找. 衡量查找算法的最主要的标准是平均查找长度(Average Search Length,简 称 ASL).平均查找长度是指在查找过程中进行的关键码比较次数的平均值. 顺序查找 ...
- Codeforces 1009G
题意略. 思路: 首先是贪心, 我们从前往后依次从小到大考虑放哪个字符, 重点是判断放了这个字符后, 对于剩下的后缀是否存在合法解. 考虑每个位置的允许放的字符集合只有2 ^ 6种, 我们预处理一个后 ...
- python查找时,不支持compound class
1.python使用如下代码查找页面上的元素时, browser.findElement_by_class_name("widget-content nopadding") 报错: ...