删除链表重复的节点
1、题目
在一个排序的链表中,如何删除重复的节点?例如:
删除前:1 -> 2 -> 3 -> 3-> 4 -> 4 -> 5
删除后:1 -> 2 -> 5
输入参数:链表的头指针
输出结果:无
2、解题
这道题的关键在于理清 找到节点—>删除节点—>链接链表 的逻辑。
因为当前链表是已排序的链表,所以可以根据前后节点的值是否相等直接判断节点是否重复,通过一个布尔变量needDelete 记录判定结果。
若没有重复,则按普通方式继续遍历即可;一旦找到重复节点,就开始向后遍历、删除,直到重复节点被全部删除为止。最后再根据删除后链表的情况进行前后链表的连接。
这道题的难点在于五个链表指针的使用:
- *pHead,链表的头指针
- *pNode,用于遍历链表的指针
- *pPreNode,用于指向遍历到的当前节点的前一个节点
- *pNext,用于指向当前节点的下一个节点(在删除节点时,指向最后一个被删除节点的下一个节点)
- *pToBeDel,用于指向被删除节点,释放内存使用
解题的具体步骤:
- 鲁棒性检查
- 先创建必需的pNode和pPreNode指针,然后进入链表的遍历
- 创建布尔变量needDelete记录是否重复的判定结果
- 创建pNext,指向当前节点的下一个节点,然后判断当前节点是否和下一节点重复
- 若不重复,继续下一个节点的循环
- 若重复,则创建pToBeDelete指向当前节点,从当前节点开始删除
- 删除结束,将被删除节点前后的链表连接起来
- 若删除了头指针,则直接将头指针指向被删除节点的下一个节点pNext
- 若未删除头指针,将pPreNode指向pNext即可
- 最后将pNode指向pNext,继续下一个节点的循环
3、代码
void DeleteDuplication(ListNode** pHead) {
if (pHead == nullptr || *pHead == nullptr)
return;
ListNode* pNode = *pHead;
ListNode* pPreNode = nullptr;
while (pNode != nullptr) {
ListNode* pNext = pNode->m_pNext;
bool needDelete = false;
//判断当前节点是否与下一节点重复
if (pNext != nullptr && pNext->m_nValue == pNode->m_nValue) {
needDelete = true;
}
//假如不重复,则进行下一次循环
if (!needDelete) {
pPreNode = pNode;
pNode = pNode->m_pNext;
}
//假如重复,则从当前节点开始删除
else {
ListNode* pToBeDel = pNode;
int value = pNode->m_nValue;
while (pToBeDel != nullptr && pToBeDel->m_nValue == value) {
//先找到下一节点,再删除
pNext = pToBeDel->m_pNext;
delete pToBeDel;
pToBeDel = nullptr;
pToBeDel = pNext;
}
//删除后,将删除节点的前后节点连接起来
//假如删除了头节点
if (pPreNode == nullptr)
*pHead = pNext;
else
pPreNode->m_pNext = pNext;
//继续下一节点的循环判断
pNode = pNext;
}
}
}
4、注意点
- 在开始删除节点的时候,记得先对pToBeDelete进行判空,防止出现空指针异常
- 删除完节点后记得要连接前后节点,且必须判断是否删除了头节点