在O(1)时间内删除链表节点。
给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。链表节点与函数的定义如下:
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
};
void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted);
思路:题目要求是O(1)时间内,基本上就告别遍历的直观方式了。“删除”==“无视”,可以这么说吧,那么找到该节点的前面一个节点,然后上节点指向下节点,“无视”了该节点,这就完成了删除。但是得到上节点的路必然是遍历。再想想,链表结点存在哪并不重要吧,重要的是第几个结点对应的数据,那么如果把下节点的值赋给该节点岂不美哉?
void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted)
{
if(!pListHead||!pToBeDeleted)
return;
//要删除的节点不是尾节点
if(pToBeDeleted->m_Next!=nullptr)
{
ListNode* pNext=pToBeDeleted->m_pNext;
pToBeDeleted->m_nValue=pNext->m_nValue;
pToBeDeleted->m_pNext=pNext->m_pNext;
}
//链表只有一个节点,删除头节点(也是尾节点)
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;
}
}
总结:那么最后要给大佬分析一下这个时间复杂度。对于n-1个非尾节点而言,我们可以在O(1)时间内把下一个界定啊的内存
复制覆盖要删除的节点,并删除下一个节点,由于仍然需要顺序查找,时间复杂度是O(n)。因此,总的平均时间复杂度是
[(n-1)xO(1)+O(n)]/n,结果还是O(1),符合要求。
感觉C#不是很适合用来考有关数据结构的算法,所以这段代码我也是理解后照抄的,没有经过实际C++测试。