13:在O(1)时间删除单链表节点

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


解析:
删除单向链表中的一个节点,常规做法是必须找到待删除节点的前一个节点才干实现。而这样做的时间复杂度是O(n)。无法满足要求。


创新想法:当我们想删除一个节点时。并不一定要删除节点本身。能够用当前节点保存它下一节点的值,然后删除它的下一个节点。

情况案例:
1. 输入节点为NULL
2. 单链表仅仅有一个节点,即删除头节点
3. 待删除节点是尾节点,即没有下一节点
4. 待删除不是尾节点

当待删除节点是尾节点时。採用常规方法:须找到待删除节点的前一个节点才干实现O(n),但对于其它的非尾节点能够以O(1)的时间删除,因此平均时间复杂度是[(n-1)*O(1) + O(n)]/n,结果还是O(1)

本题批注:
删除一个节点时。并不一定要删除节点本身,可删除它的下一个
删除一个节点,要free或delete,而且置为NULL

typedef struct ListNode {
    int val;
    struct ListNode* next;
} ListNode;
// 假设要找到待删除节点的前一结点就是O(n),
// 要想实现O(1)就不能查找。因此我们用待删除节点保存它下一节点的内容,然后删除下一节点
ListNode* DeleteElement(ListNode* head, ListNode* pToDeleted) {
    if (head == NULL || pToDeleted == NULL)
        return head;
    // 仅仅有一个节点
    if (head == pToDeleted) {
        delete pToDeleted;
        head = NULL;
        pToDeleted = NULL;
        return NULL;
    }
    if (pToDeleted->next == NULL) {
        // 待删除的为最后一个节点
        ListNode* pNode = head;
        while (pNode->next != pToDeleted) // 常规方法找到待删除前一结点
            pNode = pNode->next;
        pNode->next = NULL;
        delete pToDeleted;
        pToDeleted = NULL;
    } else {
        // 要删除的节点不是尾节点
        ListNode* pNext = pToDeleted->next;
        pToDeleted->val = pNext->val;
        pToDeleted->next = pNext->next;
        delete pNext;
        pNext = NULL;
    }
    return head;
}
原文地址:https://www.cnblogs.com/cynchanpin/p/7260171.html