题目:给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点。
思路:
在单向链表中删除一个结点,最常规的做法是从链表头结点开始,顺序遍历查找要删除的结点的前一个结点,然后把要删除的结点的next赋给要删除的结点的前一个结点的next即可完成。但是这种思路由于要顺序查找,时间复杂度为O(n)。
那是否一定需要得到被删除的结点的前一个结点呢?当然不是!我们可以很方便的得到要删除的结点的下一个结点,所以我们只需要把要删除的结点的下一个结点的内容赋值给要删除的结点的内容,然后删除要删除的结点的下一个结点即可。
注意:除了头指针和节点指针是null这种特殊输入之外(这种特殊输入是每个方法都必须考虑需要进行特殊处理的!),还有两种特殊情况,需要特殊考虑:
1.单链表只有一个结点,且要删除的结点就是这个结点,此时直接将头结点置为空即可,即head=null。
2.单链表有多个结点,但是,要删除的结点为尾节点,此时它没有下一个结点!所以我们只能从头结点开始顺序遍 历得到该结点的头结点,并完成删除操作。
时间复杂度分析:
对于n-1个非尾节点而言,我们可以在O(1)把下一个结点的内存复制覆盖要删除的结点,并删除下一个结点;对于尾节点而言,仍需顺序查找,时间复杂度为O(n)。所以平均复杂度为[(n-1)*O(1)+O(n)]/n,结果还是O(1),符合要求。
java实现:
public class DeleteNode {
class ListNode{
int data;
ListNode next;
}
public void deleteNode(ListNode head, ListNode p){//p指向要删除的结点
if(head==null||p==null)
return;
//只有一个结点的情况,且要删除的结点即为该节点
if(head==p){
head=null;
}
//有多个结点,且要删除的结点不是尾节点
else if(p.next!=null){
p.data=p.next.data;
p.next=p.next.next;
}
//有多个结点,且要删除的是最后一个结点
else{
ListNode q = head;
while(q.next!=p){
q=q.next;
}
q.next=null;
//q.next = p.next;
}
}
}
另外,值得注意的是,上述代码是基于一个假设:要删除的结点的确在链表中。我们需要O(N)的时间才能判断链表中是否包含某一结点,但是受到O(1)的限制,我们只能把确保结点在链表的责任推给deleteNode()方法的调用者,这点在面试的时候需要说明。
455

被折叠的 条评论
为什么被折叠?



