删除链表中相同的元素

简介: 链表是一种常见的数据结构,他是线性表的一种,他的典型特征就是数据结点之间通过指针相连,链表主要适合存储插入、删除操作比较频繁的数据。这篇文章总结如何删除链表中相同的元素。

前言:

链表是一种常见的数据结构,他是线性表的一种,他的典型特征就是数据结点之间通过指针相连,链表主要适合存储插入、删除操作比较频繁的数据。这篇文章总结如何删除链表中相同的元素。


题目原文



编写程序实现:建立一个单链表,然后删除单链表中“重复”的节点,使操作之后的单链表中只留下不同的结点,最后输出单链表中所有结点。


题目解析



需求很清晰,就是要删除重复元素,然后输出剩余不重复的元素即可。此外单链表的创建这里就不演示了,若是不想自己创建单链表的实现类,这个文章里可以直接去复制单链表的实现类然后直接使用即可。单链表的实现


错误的解决示例



这是一种很容易想到的解决方案,但是该方案却是不对的,且可能写完了自己都发现不了这种方案是错的,因为笔者开始就是这么写的,来一起看下这个错误的示范吧。


    //删除链表中相同的元素:错误示范
    public static void deleteRepeat(NewLinkedTable linkedTable) throws Exception{
        if(linkedTable.isEmpty())
            throw new Exception("链表为空");
        //遍历删除
        for(int i=0;i<linkedTable.length();i++){
            for(int j=i+1;j<linkedTable.length();j++){
                if(linkedTable.get(i).equals(linkedTable.get(j))){
                    linkedTable.remove(j);
                }
            }
        }
    }


1).错误思路


我们想要删除一个链表中的重复元素,那么只需要将每一个元素都和其他元素比较即可,当有其他数据元素和原先数据元素相同时,就将其他元素删除,那么最后就可以实现删除重复元素的效果。不过这种方案明显有缺陷,就是每个元素都去和其他所有数据元素比较,明显不合理,这样会有重复比较的情况出现,假设有5个元素,那么第一个元素首先会合其他所有元素比较,若是到第二个元素时还和其他所有元素比较的话,显然他和第一个元素比较就是多余的了因为之前比较过了。所以我们每次只需将当前元素和他之后的元素比较即可。这样就产生了上面的代码。假设链表有五个元素,那么删除的逻辑就是这样的,如下图(请忽略这卑劣的画技):


2021041620045310.png


2).测试该错误方案


下面创建一个单链表(使用的是这里的单链表实现:单链表的实现),然后往单链表中插入一些元素,调用该方法进行测试。

测试结果如下图所示:

20210416201054155.gif


上方代码使用头插法往链表里插入了8个数据,其中有每个数据都是有相同值,调用去重方法后都是只保留了一个,测试得出结果发现去重正确,并没有什么问题。那么秉着严谨的精神,我们再测试下另一种场景:连续重复的场景,如下:


20210416201449178.gif


这时就出现问题了,去重后的单链表依然拥有重复值,说明上方实现的去重代码有问题。下面分析下这种去重实现失败的原因。


3).分析去重失败原因


为什么会出现这种有的情况可以实现去重,有的情况又去重失败呢?仔细思考下就会发现问题所在,首先明确在测试第一种场景时成功实现了去重,说明这种情况下逻辑没有问题,问题在于第二种出现连续重复值的场景,当我们删除了一个元素时,删除的元素位置以后的元素相当于是前移了一位的,如下图,若是我们删除的是第三位的链表元素,删除完后接下来的比较理论上是应该再去与第四位的4比较,但是当我们删除3时,4所在的位置就成了第三位,这时程序继续运行比较的是第四位但是4已经变成第三位了5才是第四位,那么就是与5比较,这样正好就把相邻的元素遗漏了,若是相邻元素出现重复,则会去重失败。


20210416202248223.png


正确的解决示例



上面已经分析了错误的原因,那么问题已经清楚,解决起来其实就很容易了,主体代码不动,我们只需要在每次成功删除元素时,再重新比较下当前下标的元素即可,应用在代码里只需要加一行代码即可实现,如下:

//删除链表中相同的元素:正确示范
    public static void deleteRepeat2(NewLinkedTable linkedTable) throws Exception{
        if(linkedTable.isEmpty())
            throw new Exception("链表为空");
        //遍历删除
        for(int i=0;i<linkedTable.length();i++){
            for(int j=i+1;j<linkedTable.length();j++){
                if(linkedTable.get(i).equals(linkedTable.get(j))){
                    linkedTable.remove(j);
                    j--;                                                              //只增加了这一行代码
                }
            }
        }
    }


总结



这种删除重复元素的解决方案,同样适用于顺序表,所以这种方法适用于所有使用线性表结构存储数据的去重。为什么会适用所有线性表的去重呢?因为线性表的逻辑结构都是连续的,逻辑连续就保证了当删除一个元素时,需要将删除元素的前一个和后一个数据元素在逻辑上连接起来。所以我们用这种方法可以实现对所有线性表的去重操作。不过这种方法对于逻辑上不连续的树、图显然是不适用的。

目录
打赏
0
0
0
0
10
分享
相关文章
|
5月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
56 1
【刷题记录】移除链表元素
【刷题记录】移除链表元素
|
9月前
|
数据结构和算法学习记录——习题-移除链表元素
数据结构和算法学习记录——习题-移除链表元素
37 0
01_移除链表元素
01_移除链表元素
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
5月前
【LeetCode 06】203.移除链表元素
【LeetCode 06】203.移除链表元素
45 0
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
|
8月前
【数据结构OJ题】移除链表元素
力扣题目——移除链表元素
56 2
【数据结构OJ题】移除链表元素
|
7月前
|
【Leetcode刷题Python】203.移除链表元素
文章提供了三种删除链表中特定值节点的方法:迭代法、虚拟节点迭代删除法和递归法,并给出了相应的Python实现代码。
45 0
|
8月前
链表4(法二)------7-4 sdut-C语言实验-单链表中重复元素的删除
链表4(法二)------7-4 sdut-C语言实验-单链表中重复元素的删除
47 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等