给定单向链表的头指针以及链表中的节点指针,要求在O(1)时间内删除该节点
这里我们假设给定要删除的节点一定位于链表内。否则的话如果需要确定链表中是否包含该节点,则要O(N)的时间。
删除链表中的一个节点有两个方法,方法一如上图(a),需要删除的是节点i,此时需要获得其前一个节点h,将h由原来指向i变为指向j,然后再删除i即可。
此法需要获得删除节点的上一个节点,对于本题,由于是单向链表,如果要获得节点h,需要从头遍历链表,时间复杂度为O(N),不符合要求。
既然不能获得待删除节点的上一个节点,我们可以打一下链表后方节点的主意。如图©,如果将节点j的元素拷贝到节点i,然后再删除节点j,则最终的效果跟删除节点i是一样的。
注意此法由于需要拷贝待删除节点i的下一个节点元素,如果i为尾节点,则无法拷贝,此时仍然需要从头遍历数组,找到i的前一个节点,用旧方法删除。
另外一个需要注意的是,如果链表中只有1个元素,则只需要将头指针至为空即可。
由于只有需要删除最后一个节点时才需要遍历链表,因此平均的时间复杂度仍然是O(1)
下方为实现代码:
void DeleteNodeInList(LinkList &List, ListNode *Node){
if(List==nullptr||Node==nullptr) return;
//假设输入的Node一定在链表中
//当链表只有1个元素
if(List==Node&&List->Next==nullptr){
delete Node;
List=nullptr;
return;
}
//当删除节点为尾节点,需要从头遍历找到节点的前一个节点
if(Node->Next==nullptr){
ListNode *mPrev = List;
while(mPrev->Next!=Node) mPrev = mPrev->Next;
delete Node;
mPrev->Next = nullptr;
return;
}
//当删除节点为除尾节点以外
ListNode *NodeToBeDel = Node->Next;//真实需要删除节点
ListNode *NodeNext = NodeToBeDel->Next;//删除后Node的下一个节点
Node->Value = NodeToBeDel->Value;
Node->Next = NodeNext;
delete NodeToBeDel;
return;
}
本题完整代码在这里
总结
本题难点在于,不能用以往方法来删除链表节点。
能够想到用删除下一个节点的方法,也要能够想到当链表只有1个元素和待删除节点在链表末尾的情况。
总之在处理关于链表的问题是,要处理好几个边界条件。分别是当链表或者节点为空、链表只有一两个元素、节点处于链表头或者链表尾的情况。