1.单向链表删除节点两种方式
通常对于单向链表,有两种删除方式:
1.记录前面的一个节点,把被删除节点的后继设为前驱节点的下一个节点,但是要注意头结点的问题 时间复杂度为O(n)
2.不需要记录前驱节点,我们只需要把被删除节点的后继节点的内容复制到被删除节点中,然后删除这个后继节点,时间复杂度为O(1),同第一种方式一样,当删除的是尾节点的时候,不能采用这种方式,必须使用第一种从前向后遍历的方式,时间复杂度此时为O(n)
struct ListNode{
int val;
ListNode* next;
ListNode() {
}
ListNode(int k):val(k),next(nullptr) {
}
};
class Solution{
public:
Solution() //构造函数
{
}
~Solution() //析构函数
{
}
//对于非尾节点采用第二种方式,如果只有一个节点,那么删除后要注意空指针的问题,对于尾节点要采用第一种方式
void deleteNode(ListNode** pHead,ListNode* ToBeDelete)
{
//判断其是否为尾节点
if(ToBeDelete->next!=nullptr)
{
//不是尾节点
ListNode* nextNode = ToBeDelete->next;
ToBeDelete->val = nextNode->val;
ToBeDelete->next = nextNode->next;
delete nextNode;
nextNode = nullptr;
}
else {
//当只有一个节点时
if(*pHead == ToBeDelete)
{
delete ToBeDelete;
ToBeDelete = nullptr;
(*pHead) = nullptr;
}
else {
//当有多个节点时,删除尾节点
//采用第一种方式,依次遍历即可
ListNode* pNode = (*pHead);
ListNode* pre = nullptr;
while(pNode->next!=nullptr)
{
pre = pNode;
pNode = pNode->next;
}
delete pNode;
pNode = nullptr;
pre->next = nullptr;
}
}
}
};
2.删除链表中重复元素
我们要把当前节点的前一个节点(pre)和后面值比当前节点的值大的节点相连,我们要确保pre始终与下一个没有重复的节点连接在一起。
//删除链表中重复元素,注意一些边界性测试
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
Solution()
{
}
~Solution()
{
}
void deleteNode(ListNode** pHead)
{
if(pHead==nullptr||*pHead==nullptr) return;
ListNode* pre = nullptr;
ListNode* pNode = *pHead;
while(pNode!=nullptr)
{
ListNode* nextNode = pNode->next;
bool flag = true;
if(nextNode!=nullptr&&nextNode->val==pNode->val) flag = false;
if(flag) {
pre = pNode;
}
else {
int Value = pNode->val;
ListNode* pToBeDelete = pNode;
while(pToBeDelete!=nullptr&&pToBeDelete->val==Value)
{
nextNode = pToBeDelete->next;
delete pToBeDelete;
pToBeDelete = nullptr;
pToBeDelete = nextNode;
}
if(pre==nullptr) {
(*pHead) = nextNode;
}
else {
pre->next = nextNode;
}
}
pNode = nextNode;
}
}
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==nullptr) return nullptr;
deleteNode(&pHead);
return pHead;
}
};