问题一:在O(1)时间内删除链表节点。给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。链表节点定义如下:
struct ListNode
{
int m_nValue;
ListNode *m_pNext;
};
解题思路:在单向链表中删除一个节点,直观的做法是从链表的头节点开始,顺序遍历查找要删除的节点,并在链表中删除该节点。该方法的时间复杂度是O(n)。另一种思路,可以把下一个节点的内容复制到需要删除的节点上覆盖原有的内容,再把下一个节点删除。此时需要考虑两种特殊情况,1.如果要删除的节点位于链表的尾部,那么它就没有下一个节点,此时仍然需要从链表的头节点开始,顺序遍历得到该节点的前序节点,并完成删除操作。2.如果链表中只有一个节点,而又要删除链表的头节点(也是尾节点),那么在删除节点之后,还需要把链表的头节点设置位nullptr。
void DeleteNode(ListNode **pListHead, ListNode *pDeleted)
{
if(!pListNode || !pDeleted)
return ;
if(pDeleted->m_pNext != nullptr)
{
ListNode *pNext = pDeleted->m_pNext;
pDeleted->m_nValue = pNext->m_nValue;
pDeleted->m_pNext = pNext->m_pNext;
delete pNext;
pNext = nullptr;
}
else if(*pListHead == pDeleted)
{
delete pDeleted;
pDeleted = nullptr;
*pListHead = nullptr;
}
else
{
ListNode *pNode = *pListHead;
while(pNode->m_pNext != pDeleted)
{
pNode = pNode->m_pNext;
}
pNode->m_pNext = nullptr;
delete pDeleted;
pDeleted = nullptr;
}
}
问题二:删除链表中重复的节点。在一个排序的链表中,如何删除重复的节点。
解题思路:从头遍历整个链表,如果当前节点的值与下一个节点的值相等,那么他们是重复的节点,需要被删除。为了保证删除之后的链表仍然是相连的,就需要把当前节点的前一个节点和后面值比当前节点的值大的节点相连,我们要确保链表没断。
void DeleteDuplication(ListNode **pHead)
{
if(pHead == nullptr || *pHead == nullptr)
return ;
ListNode *pPreNode = nullptr;
ListNode *pNode = *pHead;
while(pNode != nullptr)
{
ListNode *pNext = pNode->m_pNext;
bool needDelte = false;
if(pNext != nullptr && pNext->m_nValue == pNode->m_nValue)
needDelte = true;
if(!needDelete)
{
pPreNode = pNode;
pNode = pNode->m_pNext;
}
else
{
int value = pNode->m_nValue;
ListNode *pToDelete = pNode;
while(pToDelete != nullptr && pToDelete->m_nValue == value)
{
pNext = pToDelete->m_pNext;
delete pToDelete;
pToDelete = nullptr;
pToDelete = pNext;
}
if(pPreNode == nullptr)
*pHead = pNext;
else
pPreNode->m_pNext = pNext;
pNode = pNext;
}
}
}