《剑指offer》第十八题:在O(1)时间删除链表结点

// 面试题18(一):在O(1)时间删除链表结点
// 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该
// 结点。

#include <cstdio>
#include "List.h"

void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
    if (pListHead == nullptr || pToBeDeleted == nullptr)
        return;

    //多个节点, 且位于中间
    if (pToBeDeleted->m_pNext != nullptr)
    {
        ListNode* pNext = pToBeDeleted->m_pNext;
        pToBeDeleted->m_nValue = pNext->m_nValue;
        pToBeDeleted->m_pNext = pNext->m_pNext;
        delete pNext;
        pNext = nullptr;
    }
    //单节点,
    else if (*pListHead == pToBeDeleted)
    {
        delete pToBeDeleted;
        pToBeDeleted = nullptr;
        *pListHead = nullptr;

    }
    //多节点, 处于尾部
    else
    {
        ListNode* pNode = *pListHead;
        while (pNode->m_pNext != pToBeDeleted)
            pNode = pNode->m_pNext;

        pNode->m_pNext = nullptr;
        delete pToBeDeleted;
        pToBeDeleted = nullptr;
    }
}

// ====================测试代码====================
void Test(ListNode* pListHead, ListNode* pNode)
{
    printf("The original list is: \n");
    PrintList(pListHead);

    printf("The node to be deleted is: \n");
    PrintListNode(pNode);

    DeleteNode(&pListHead, pNode);

    printf("The result list is: \n");
    PrintList(pListHead);
}

// 链表中有多个结点,删除中间的结点
void Test1()
{
    ListNode* pNode1 = CreateListNode(1);
    ListNode* pNode2 = CreateListNode(2);
    ListNode* pNode3 = CreateListNode(3);
    ListNode* pNode4 = CreateListNode(4);
    ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    Test(pNode1, pNode3);

    DestroyList(pNode1);
}

// 链表中有多个结点,删除尾结点
void Test2()
{
    ListNode* pNode1 = CreateListNode(1);
    ListNode* pNode2 = CreateListNode(2);
    ListNode* pNode3 = CreateListNode(3);
    ListNode* pNode4 = CreateListNode(4);
    ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    Test(pNode1, pNode5);

    DestroyList(pNode1);
}

// 链表中有多个结点,删除头结点
void Test3()
{
    ListNode* pNode1 = CreateListNode(1);
    ListNode* pNode2 = CreateListNode(2);
    ListNode* pNode3 = CreateListNode(3);
    ListNode* pNode4 = CreateListNode(4);
    ListNode* pNode5 = CreateListNode(5);

    ConnectListNodes(pNode1, pNode2);
    ConnectListNodes(pNode2, pNode3);
    ConnectListNodes(pNode3, pNode4);
    ConnectListNodes(pNode4, pNode5);

    Test(pNode1, pNode1);

    DestroyList(pNode1);
}

// 链表中只有一个结点,删除头结点
void Test4()
{
    ListNode* pNode1 = CreateListNode(1);

    Test(pNode1, pNode1);
}

// 链表为空
void Test5()
{
    Test(nullptr, nullptr);
}

int main(int argc, char* argv[])
{
    Test1();
    Test2();
    Test3();
    Test4();
    Test5();

    return 0;
}

测试代码

分析:代码假设要删除的节点的确在链表中。需要O(n)时间遍历链表才可以确认,可以讨论这个假设,考虑更为全面。

原文地址:https://www.cnblogs.com/ZSY-blog/p/12562615.html

时间: 2024-11-19 02:02:46

《剑指offer》第十八题:在O(1)时间删除链表结点的相关文章

剑指offer第十八题 顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10. 解题思路:一次去掉一个外圈,当最后只剩一行或一列时停止递归.(ps:这题就是绕,仔细点就解决了!!!) 1 import java.util.ArrayList; 2 public class Solution { 3 publ

剑指offer(五十八)之正则表达式匹配

题目描述 请实现一个函数用来匹配包括'.'和'*'的正则表达式.模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次). 在本题中,匹配是指字符串的所有字符匹配整个模式.例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配 代码: <span style="color:#000099;">pu

剑指offer(四十八)之复杂链表的复制

题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点). 代码: <span style="color:#000099;">import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import java.util.Set; public class Solution { public RandomListNod

剑指offer(二十八)之丑数

题目描述 把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含因子7. 习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第N个丑数. 思路分析: 1.首先,丑数都是由前5个丑数1,2,3,4,5乘以因子2,3,5才得到的. 2.这里将得到的丑数都存放在数组中.分析一下得到第6个丑数的过程,其他丑数类比. 3.1 将前5个丑数乘以2,然后与第5个丑数进行比较,找出第一个乘以2大于第5个丑数的丑数,将其放在min2中. 3.2 将前5个丑数乘以

剑指offer(三十八)之第一个只出现一次的字符位置

题目描述 在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符的位置.若为空串,返回-1.位置索引从0开始 思路分析: 1.先把字符串存到字节数组当中 2.设置一个标志位,再用两个FOR循环 <span style="font-family:SimSun;font-size:24px;">public class Solution { public int FirstNotRepeatingChar(String str)

【Java】 剑指offer(17) 在O(1)时间删除链表结点

本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. 思路 通常那样从头开始查找删除需要的时间为O(n),要在O(1)时间删除某结点,可以这样实现:设待删除结点i的下一个结点为j,把j的值复制到i,再把i的指针指向j的下一个结点,最后删除j,效果就相当于删除j. 注意特殊情况:1.当待删除结点i为尾结点时,无下一个结点,则只能从头到尾顺序遍历:2.当链

【剑指offer】第四题 替换空格

/** * 剑指offer 第4题 替换空格 * 特点:1.先扫描串中的空格数,计算好替换后的长度 * 2.使用双指针,从后面开始向前替换,避免从前开始每次替换后就要移动后面的所有的数据 * 测试用例:特殊:有多个空格 * 错误:数组长度不够,字符串为空 * */ package javaTrain; public class Offer4 { public static void main(String[] args) { String a = "Hello I am Daisy Dong!&

第五十八题(从尾到头输出链表)

58.从尾到头输出链表. 题目:输入一个链表的头结点,从尾到头反过来输出每一个结点的值. 思路:题不难,提供几种思路 1.使用栈的先进后出特性实现,遍历链表元素依次入栈,再出栈就可以达到目的 2.使用数组先暂存顺序遍历的结果,再对数组反向遍历就可以. 3.递归,也就是这里採用的方法. C++代码: #include "stdafx.h" #include<ctime> #include<iostream> namespace MS100P_58 { void r

【剑指offer】十,反转链表

题目描述 输入一个链表,反转链表后,输出链表的所有元素. 分析:此题学过数据结构的应该会首先想到链表建立时所采用的头插法,即每一个新插入进来的点均插在链表头.代码如下: 1 /* 2 public class ListNode { 3 int val; 4 ListNode next = null; 5 6 ListNode(int val) { 7 this.val = val; 8 } 9 }*/ 10 public class Solution { 11 public ListNode R