如何删除链表中值重复的节点

前言

??最近在刷《剑指offer》的题,其中有一道题目叫做删除链表中重复的节点,我想了半天没想到比较好的解决办法,于是看了看大佬的解析(菜哭了)。不看不知道,一看吓一跳,这尼玛写的也太妙了,忍不住写篇博客记录一下这个解题思路和代码。

题目描述

??在一个排好序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

解题思路

??这道题我们分两种情况来考虑:

  1. 首先第一种情况:头节点的值存在重复;比如1->1->1->2->3->3->4,前面这个链表的头节点重复了3次,所以这时候,我们应该舍弃前3个重复的节点1,将2作为新的头节点,再继续向后判断;
  2. 第二种情况就是头节点并不与它的下一个节点重复;比如上面的这个链表,我们去除了前面的3个1之后,剩下2->3->3->4,这时候,头节点不与后面的节点重复了,那我们保留头节点,并继续向后判断,发现后面后面的两个3发生了重复,于是,我们去除这个两个节点,并让原来头节点的next指向去除重复后的下一个位置,也就变成了2->4;若4后面还有其他重复,则我们去除重复后,让4指向剩下的部分;

代码实现

??其实上面的思路并不是很难想到,关键是代码如何实现呢?下面这个代码就是大佬对于上面这个思路的实现:

public ListNode deleteDuplication(ListNode pHead) {
    // 若头节点为空,或者链表只有一个节点,则必没有重复,值将返回
    if(pHead == null || pHead.next == null) {
        return pHead;
    }

    // 保存头节点的下一个节点,上面已经判断了pHead.next不是空
    ListNode next = pHead.next;
    // 若头节点的值与下一个节点的值相同
    if(pHead.val == next.val) {
        do{
            // 则继续向前找出与头节点重复的节点
            // 直到找到第一个与头节点不同的节点后,退出循环
            next = next.next;
        }while(next != null && next.val == pHead.val);

        // 舍弃前面的所有重复节点,将当前第一个与头节点不同的节点作为头节点,递归调用原方法,并直接返回
        return deleteDuplication(next);
    }else {
        // 若头节点与它的下一个节点值不同,则将头节点的下一个节点作为头节点,递归调用方法
        // 并将返回值赋给头节点的next属性
        pHead.next = deleteDuplication(next);
        return pHead;
    }
}
// 以下是节点ListNode
class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}

??上面的代码我加了点注释,看得难受可以复制到编辑器中,删掉注释再看。

??上面这段代码,给我的感觉就是把递归用的出神入化(可能是我太菜了)。除去注释,短短几行代码,就将上面的思路完全实现,下面我来解读一下:

??上面的代码首先做了特判,若传入的头节点是空,或者没有后续节点,那就不用去重,直接返回。这之后,先将头节点的下一个节点保存。

??我们先判断当前是否满足前面说的第一种情况:头节点发生了重复,若发生了这种情况,就一直向后找,直到找到第一个不与头节点重复的节点,然后我们舍弃前面的节点,把这个节点当作头节点,递归调用方法,并直接将返回值返回,这相当于是把后面剩下的部分当作一条新的链表,而前面重复的就直接舍弃了;

??若当前链表是我们之前说的第二种情况:头节点不重复,则我们将头节点的下一个节点作为参数,递归调用原方法,将除去头节点后的子链表看作是一个新链表,而方法返回值就是这个子链表去重后的链表,我们将其与原来头节点关联,就完整地去重了。

??上面代码最精妙的地方就是递归,将原链表中除去头节点的剩余部分,当作一个新链表进行处理,短短几行代码,就实现了去重。

原文地址:https://www.cnblogs.com/tuyang1129/p/12177777.html

时间: 2024-07-30 18:14:15

如何删除链表中值重复的节点的相关文章

删除链表中的重复节点、剩余节点逆序输出

#include <stdlib.h> #include <algorithm> #include <functional> #include <iostream> #include "oj.h" using namespace std; /* 功能: 输入一个不带头节点的单向链表(链表的节点数小于100),删除链表中内容重复的节点(重复的节点全部删除),剩余的节点逆序倒排. 输入: pstrIn: 输入一个不带头节点的单向链表 输出:

[华为机试练习题]24.删除链表中的重复节点、剩余节点逆序输出

题目 描述: 题目描述: 输入一个不带头节点的单向链表(链表的节点数小于100),删除链表中内容重复的节点(重复的节点全部删除),剩余的节点逆序倒排. 要求实现函数: void vChanProcess(strNode * pstrIn,strNode * pstrOut); [输入] pstrIn:输入一个不带头节点的单向链表 [输出] pstrOut:删除内容重复的节点(重复的节点全部删除),剩余节点逆序输出(不带头节点,链表第一个节点的内存已经申请). [注意]只需要完成该函数功能算法,中

栈和队列----删除无序单链表中值重复出现的节点

删除无序单链表中值重复出现的节点 给定一个无序单链表的头节点head,删除其中值重复的节点 例如: 1->2->3->3->4->4->2->1->1->null 删除之后变为 1->2->3->4->null 方法1:如果链表长度为N,时间复杂度达到O(N) 方法2:如果要求空间复杂度为O(1),应该怎样实现 [解析] 方法1:利用哈希表去实现 使用哈希表,因为头节点是不用删除的节点,所以首先将头节点放入到哈希表中,然后从下一

删除链表中的重复节点

这里的删除是只要有重复就要全部删除,如1->2->2->3,删除之后就是1->3. #include<stdio.h> #include<stdlib.h> struct ListNode { int val; struct ListNode *next; }; struct ListNode* deleteDuplicates(struct ListNode* head) { if(NULL==head||NULL==head->next) retu

删除无序链表中值最的节点.C语言实现.2016-04 自考真题

removemax(LinkedList head){ LinkedList p,q; int max; if(head->next==NULL) return ; p=head->next; max=p->data; while(p->next){ p=p->next; if(p->data>max) max=p->data; } p=head; while(p->next){ q=p->next; if(q->data==max){ p

LintCode Python 简单级题目 112.删除链表中的重复元素

题目描述: 给定一个排序链表,删除所有重复的元素每个元素只留下一个. 您在真实的面试中是否遇到过这个题? Yes 样例 给出 1->1->2->null,返回 1->2->null 给出 1->1->2->3->3->null,返回 1->2->3->null 标签 链表 题目分析: 给定一个排序链表,删除所有重复的元素每个元素只留下一个. 源码: """ Definition of ListNod

建立一个单链表,并删除链表中值为W的元素

#include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> #include<malloc.h> using namespace std; typedef struct node { int data; struct node *next;//指向类型完全相同的指针 int len; } Lnode,*Linklist; //一个是结构体类型,一个是结构体

83删除链表中的重复元素

1.思路 吸取了前几道题设置头节点重新插入的想法 建立空的头节点,和一个指向结点的指针p用来控制插入的位置 判断第一个值和第二个值是否相等相等,链表头指针向后移动,直至不等,把head结点插入到空结点后面,直至完成 2.错误 错误提示:Line 16: Char 18: runtime error: member access within null pointer of type 'struct ListNode' (solution.cpp) 错误原因:没有判断当前指针是否指向了一个有意义的

删除链表中的指定元素节点

Remove all elements from a linked list of integers that have valueval. Have you met this question in a real interview? Yes Example Given 1->2->3->3->4->5->3, val = 3, you should return the list as1->2->4->5 要注意开始的节点是否是要删除节点,还有中间