剑指Offer-18:删除链表的节点

题目1:在O(1)的时间内删除链表节点

给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。

问题解析:

链表节点与函数的定义如下:

struct ListNode{
    int value;
    ListNode* next;
    ListNode(int val): value(val), next(nullptr) {}
};

链接:

剑指Offer(第2版):P119

思路标签:

数据结构:链表

后节点替换指定节点。

解答:

1. C++
  • 一般的,要从单向链表中删除一个指定的节点,我们需要知道其前一节点和后一节点,后一节点由其next属性很容易得知,但是如果要知道其前一节点需要对链表进行遍历,遍历的时间复杂度就是O(n);
  • 但是换一种思路我们也可以不需要知道删除节点的前一个节点:用后一节点完全复制覆盖删除节点,再删除后一节点;
  • 注意,如果指定删除节点位于节点的尾部,没有可以用来替换的节点,那么我们就还是需要从头到尾遍链表,寻找其前一个节点;
  • 同时,注意链表中只有一个元素的情况,需要将头节点设置为nullptr。
void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted) {
    if (!pListHead || !pToBeDeleted)
        return;

    //要删除的节点不是尾节点
    if (pToBeDeleted->next != nullptr) {
        ListNode* pNext = pToBeDeleted->next;
        pToBeDeleted->value = pNext->value;
        pToBeDeleted->next = pNext->next;

        delete pNext;
        pNext = nullptr;
    }
    //只有一个节点的情况
    else if (*pListHead == pToBeDeleted) {
        delete pToBeDeleted;
        pToBeDeleted = nullptr;
        *pListHead = nullptr;
    }
    //要删除的节点是尾节点
    else {
        ListNode* pNode = *pListHead;
        while (pNode->next != pToBeDeleted) {
            pNode = pNode->next;
        }

        pNode->next = nullptr;
        delete pToBeDeleted;
        pToBeDeleted = nullptr;
    }
}
  • 注意头结点指针是指向指针的指针。

题目2:删除链表中重复的节点

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。

Example:

例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

链接:

剑指Offer(第2版):P122

思路标签:

数据结构:链表

解答:

1. C++
  • 因为要删除重复的节点,所以需要保存重复节点的前一个节点;
  • 需要设置重复的标志。
class Solution {
public:
    ListNode* deleteDuplication(ListNode** pHead)
    {
        if (pHead == nullptr || *pHead == nullptr) return;

        ListNode* pPreNode = nullptr;
        ListNode* pNode = *pHead;
        while (pNode != nullptr) {
            ListNode* pNext = pNode->next;
            bool needDelete = false;
            if (pNext != nullptr && pNext->val == pNode->val)
                needDelete = true;

            if (!needDelete) {
                pPreNode = pNode;
                pNode = pNode->next;
            }
            else {
                int value = pNode->val;
                ListNode* pToBeDeleted = pNode;
                while (pToBeDeleted != nullptr && pToBeDeleted->val == value) {
                    pNext = pToBeDeleted->next;
                    delete pToBeDeleted;
                    pToBeDeleted = pNext;
                }

                pNode = pNext;
                if (pPreNode == nullptr)
                    *pHead = pNode;
                else
                    pPreNode->next = pNode;
            }
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值