删除链表的节点 :给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。
分析:因为题目直接给定了要被删除的节点,因此如果想在O(1)时间内删除给定节点,我们可以把要被删除的下一节点覆盖本节点,然后删除下一个节点即可,但有两种特殊情况,首先是当整个链表只有这么一个节点的时候,那就只把把链赋值成nullptr,其次是如果该节点是链表的最后一个节点,但是链表不是只只有一个节点,这样的话就得利用顺序遍历找到本节点的前一节点然后把本节点删除。
#include<iostream>
using namespace std;
//O(1)时间内删除节点
struct ListNode{
int value;
ListNode* next;
};
void DeleteNode(ListNode** pListNode,ListNode *pToBeDeleted){
if(!pListNode || !pToBeDeleted)
return ;
//要删除的节点不是尾结点
if(pToBeDeleted->next != nullptr){
//那就用后一个节点覆盖前一个,然后删除后一个节点
ListNode* pNext = pToBeDeleted -> next;
pToBeDeleted->value = pNext->value;
pToBeDeleted->next = pNext->next;
delete pNext;
}
else if(*pListNode == pToBeDeleted) {
//如果链表只有一个节点
delete pToBeDeleted;
pToBeDeleted = nullptr;
pListNode = nullptr;
}else{
//如果有多个节点,然后删除的是最后一个,要用顺序搜索
ListNode* p = *pListNode;
while(p->next!=pToBeDeleted)
p = p->next;
p->next = nullptr;
delete pToBeDeleted;
pToBeDeleted = nullptr;
}
}
复杂度分析:
*时间复杂度:因为对于n-1个非尾节点,可以用O(1)时间删除,对于一个最尾节点,要用O(n),那么综上,计算得平均时间复杂度为[(n-1)O(1) + (n)]/n得到O(1)。
删除链表中重复的节点:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
分析:删除重复结点,可以定义一个标志位,首先用p来遍历链表,用pre保存其前驱结点,pNext来表示p的下一结点,判断是否重复可以利用pNext && pNext->val == p->val ,那我们就设置标志位为true,如果为false就直接移动指针,如果为true就得进行循环,反复比较结点的值是否等于value,然后删除,最后特别注意当pre为nullptr就表示从链头删除,那么就得把pHead=p,如果不是的话就直接把pre->next = p。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
ListNode* pre = nullptr,*p = pHead,*pNext = nullptr,*ret = pHead;
bool toDelete = false;
while(p!=nullptr){
toDelete = false;
pNext = p->next;
if(pNext && pNext->val == p->val){
toDelete = true;
}
if(!toDelete){
//如果不一样就直接移动指针
pre = p;
p = p->next;
}else{
//如果一样就得把所有重复的节点删除掉
int value = p->val;
while(p && p->val == value){
//凡是重复的节点都删除掉
//但是删除的时候要保存其后一个节点,否则会断链
pNext = p->next;
delete p;
p = pNext;
}
if(pre!=nullptr){
pre->next = p;
}else{
ret = p;
}
}
}
return ret;
}
};