剑指 18(2) 删除链表中的重复节点

65 篇文章 1 订阅

剑指 18(2) 删除链表中的重复节点

原题目

在一个排序的链表中,删除重复的节点

示例1:

原链表:1-> 2-> 3-> 3-> 4-> 4-> 5
删除后:1-> 2 -> 5

考查知识点

嵌套指针(指针的指针)


知识点记录

设计一个函数,首先要确定两点:传入参数返回值。这是我们设计函数的最重要的两点即我有什么样的信息,要去解决什么问题,最后才是怎样利用手里的信息去解决问题

题目没有给传入参数,我们自己设计,这里就要结合题目经验,链表问题一般都是根据头结点来进行后续操作。

这里要注意的就是,如果题目不是直接返回头节点,那么我们就要将传入的形参头结点设置为嵌套指针(即指针的指针),比如ListNode **head,这是因为我们可能在函数操作中改变头结点,比如删除原来的头结点或者设置新的头结点。

举一个形象的例子,如果是查询某链表中是否存在值为val的节点,查询函数可以声明如下:

bool isExist(ListNode *head, int val);

isExist函数传入的头结点就是单一的指针,head这个形参其实是传值调用,实参头结点指针传值赋给形参,在isExist函数结束后,形参head销毁,对实参头结点指针没有影响。

但是如果是改变头结点的函数,代码如下:

void changeHead(ListNode **head)void changeHead(ListNode *&head)

changeHead必须为指针的指针,这是因为此时的形参head要传址调用,在changeHead内部能够真正改变形参背后的实参头结点指针。

比如如下的交换swap函数:代码源自学习链表时遇到的问题:为什么要把一个头结点声明成结点为指针的指针呢?

void swap(int a, int b)  
 {
     int temp = a;
     a = b;
     b = temp;
  }
void swap1(int *a, int *b)
  {
    int temp = *a;
    *a = *b;
    *b = temp;
  }
void main()
 {
   int m = 1, n = 2;
   swap(m, n);
   cout << m << endl;  //1
   cout << n << endl;  //2 没有变化

   swap1(&m, &n);
   cout << m << endl;  //2
   cout << n << endl;  //1 有变化
 }

解法

主要思想就是如果当前节点Node与下一节点nextNode的值相同,删除当前节点、释放内存,这里需要注意对头节点的操作。如果头结点时当前节点并且与下一节点重复,应该更改头结点。

还有一点是NodeheadtoBeDeletepreNodenextNode这几个指针的指向顺序的更改。

class Solution{
public:
    void DeleteDuplication(ListNode **head)
    {
        if (head == nullptr || *head == nullptr)    return;

        ListNode *preNode = nullptr;        //当前节点的前一个节点
        ListNode *Node = *head;             //当前节点
        while (Node != nullptr)
        {
            ListNode *nextNode = Node->next;    //当前节点的下一节点
            bool needDelete = false;
            if (nextNode != nullptr && nextNode->val == Node->val)
                needDelete = true;
            if (!needDelete)
            {
                preNode = Node;
                Node = Node->next;
            }
            else
            {
                int value = Node->val;
                ListNode *toBeDelete = Node;        //删除与下一节点重复的当前节点
                while (toBeDelete != nullptr && toBeDelete->val == value)
                {
                    nextNode = toBeDelete->next;
                    //删除 toBeDelete指向的节点
                    delete toBeDelete;
                    toBeDelete = nullptr;

                    toBeDelete = nextNode;
                }
                if (preNode == nullptr)
                    *head = nextNode;
                else
                    preNode->next = nextNode;
                Node = nextNode;
            }
        }
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值