题目描述
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点
初始条件
class ListNode{
int val;
ListNode next;
ListNode(int val){
this.val=val;
}
}
思路:单向链表,删除结点,先找到该结点,从头遍历到待删除结点,时间O(n)。删除时保证链表不断。
public static void DelNodeInListO_n(ListNode pListNode,ListNode pToBeDeleted){
if(pListNode==null||pToBeDeleted==null)
return;
//case1:deleted node is head node
//case2:deleted node is not head node
//case1
if(pListNode==pToBeDeleted){
pListNode=null;
pToBeDeleted=null;
}//end case1
//case2
else{
ListNode pNode=pListNode;
while(pNode.next!=pToBeDeleted){
pNode=pNode.next;
}
pNode.next=pToBeDeleted.next;
//delete pToBeDeleted;
pToBeDeleted=null;
}
}
如何实现O(1)的算法?
删除一个结点,总是要找到它的前一个结点p,使p.next=p.next.next。由单向链表没有指向前面结点的指针,所以只能从头遍历。找到后继结点q只需O(1),我们可以将q的值赋值给p,然后删除q,就相当于删除了原来的结点p。
/**
*
*/
package com.su.biancheng;
import java.util.ArrayList;
import java.util.List;
/**
* @title DeleteNodeInList.java
* @author Shuai
* @date 2016-4-10下午3:38:38
*/
public class DeleteNodeInList {
public static class ListNode{
int val;
ListNode next;
ListNode(int val){
this.val=val;
}
}
public static void DelNodeInList(ListNode pListNode,ListNode pToBeDeleted){
if(pListNode==null||pToBeDeleted==null)
return;
//case1:deleted node is not tail node
//case2:list has only one node,delete head node(tail node)
//case3:list has more than one node,delete tail node
//case1
//new nextNode of deleted node
//copy the content of the nextNode to cover toBeDeletednode
//delete nextNode is equal to delete toBeDeletednode
if(pListNode.next!=null){
ListNode nextNode=pToBeDeleted.next;
pToBeDeleted.val=nextNode.val;
pToBeDeleted.next=nextNode.next;
//delete nextNode;
nextNode=null;
}
//case2
else if(pListNode==pToBeDeleted){
//delete pToBeDeleted;
pToBeDeleted=null;
pListNode=null;
}
//case3
//tail node has no nextNode,only traverse list
else{
ListNode pNode=pListNode;
while(pNode.next!=pToBeDeleted){
pNode=pNode.next;
}
pNode.next=null;
//delete pToBeDeleted;
pToBeDeleted=null;
}
}
public static void PrintList(ListNode pListNode){
while(pListNode!=null){
System.out.print(pListNode.val+"-->");
pListNode=pListNode.next;
}
System.out.println("null");
}
public static void main(String[] args){
List<ListNode> list=new ArrayList<ListNode>();
list.add(new ListNode(1));
list.add(new ListNode(2));
list.add(new ListNode(3));
list.add(new ListNode(4));
list.add(new ListNode(5));
for(int i=0;i<list.size();i++){
ListNode listNode=list.get(i);
if(i+1<list.size()){
listNode.next=list.get(i+1);
}
}
ListNode pListNode=list.get(0);
ListNode pToBeDeleted=list.get(3);
System.out.println("before delete");
PrintList(pListNode);
DelNodeInList(pListNode,pToBeDeleted);
System.out.println("after deleted ");
PrintList(pListNode);
}
}
Note
几种特殊情况:
case1:没有下一个结点,即删除结点是尾结点
case2:如果链表只有一个结点(既是尾结点,又是头结点),需要把头结点置为空
case3:其他情况,只需把结点值复制,然后保持链表不断,使被删结点为空
Note:
时间复杂度:
[(n-1)*O(1)+O(n)]/n=O(1)
如果待删除结点不在链表中,需要O(n)判断