一:题目描述
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。
二:解题思路
最常规的做法:从链表的头指针开始顺序遍历链表,找到要删除的指针,并在链表中删除该指针。时间复杂度O(n)
我们为什么要遍历链表呢?因为我们想找到要删除结点 i 的前一个结点 j ,删除 i 的操作 :
pj->next=pi->next ;
delete pi;
pi=NULL //防止野指针的问题
因为单链表只有next指针,所以要遍历。
那么一定要知道要删除结点的前一个结点么?--答案当然是否定的,要不然这个题怎么做呢!
解决方法:
将要删除结点的下一个结点内容复制需要删除的结点上覆盖原始的内容,再把下一个结点删除,那不就相当于删除的指定结点。
需要考虑的问题:
1.删除结点有下一个结点
----按照上面的思路进行
2.删除结点没有下一个结点,是尾结点
---这个时候就需要从头遍历链表找到要删除的结点的前一个节点
3.链表中只有一个结点,删除的结点既是头结点也是尾结点
---删除该结点,将头指针置NULL
4.链表为空,或要删除的结点为空
--函数开始时,加入判断
5.要删除的结点不在链表中(如果要解决这个问题,需要遍历一遍链表,不符合时间要求,我们默认要删除的结点在链表中这个假设)
时间复杂度:[(n-1)*O(1)+1*O(n)]/n=O(1)
三:代码实现
ListNode* deleteNode(ListNode* head, ListNode* pDelete){
if (head == NULL || pDelete == NULL)
return NULL;
//要删除的结点的下一个结点不为空
if (pDelete->next != NULL){
ListNode* pNode = pDelete->next;
//将下一个结点的信息赋值给pDelte
pDelete->val = pNode->val;
pDelete->next = pNode->next;
//删除下一个结点
delete pNode;
pNode = NULL; //防止野指针的情况
}//if
else if (head == pDelete){
//如果链表只包含一个结点,要删除的是头结点
delete pDelete;
pDelete = NULL;
cout << "只有一个结点,删除头指针" << endl;
//头指针置NULL
head = NULL;
}
else{
//删除尾指针
//遍历链表
ListNode* pNode = head;
//找到要删除结点的前一个结点
while (pNode->next != pDelete){
pNode = pNode->next;
}
pNode->next = NULL;
delete pDelete;
pDelete = NULL;
}
return head;
}//deleteNode