题目:
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数的定义如下:
struct ListNode{
int m_nValue;
ListNode* m_pNext;
}
void DeleteNode(ListNode ** pListHead, ListNode* pToBeDeleted);
第一思路:时间复杂度为O(n)的方法
从链表的头结点开始,顺序遍历查找要删除的结点,并在链表中删除该结点。时间复杂度为O(n)。其实这和数组没有什么区别了,没有充分利用链表的特点。
代码实现:
/**
* 定义单链表的结构体
* @author Peter
*/
public class ListNode {
//属性定义成公开的方便调用和使用
public int data;
//公有属性
public ListNode next;
}
//O(n)时间复杂度删除pDelNode结点
public void deleteNode1(ListNode pHead, ListNode pDelNode){
if(pHead==null || pDelNode==null){
return;
}
if(pHead == pDelNode){ //删除的是头结点
ListNode pNext = pDelNode.next;
pDelNode.data = pNext.data;
pDelNode.next = pNext.next;
return;
}
//利用O(n)的时间复杂度删除结点
for (ListNode pNode = pHead; pNode.next!=null; pNode = pNode.next) {
if(pNode.next == pDelNode){
pNode.next = pNode.next.next;
break;
}
}
}
第二思路:在O(1)的时间复杂度删除结点
因为从某个链表的结点可以知道链表的下一个结点,故可以把下一结点的内容复制到需要删除的结点上覆盖原有的内容,再把下一个结点删除,就相当于把当前需要删除的结点删除。这是分为三种情况:删除的结点不在链表尾部;链表只有一个结点,删除头结点;链表中有多个结点,删除尾部结点。
代码实现:
//O(1)时间删除链表的结点
public void deleteNode(ListNode pHead, ListNode pDelNode){
if(pHead==null || pDelNode==null){
return;
}
if(pDelNode.next!=null){ //要删除的结点不是尾部结点
ListNode pNext = pDelNode.next;
pDelNode.data = pNext.data;
pDelNode.next = pNext.next;
}else if(pHead == pDelNode){ //链表只有一个结点,删除头结点
pHead = null;
pDelNode = null;
}else{ //链表中有多个结点,删除尾结点
ListNode pNode = pHead;
while(pNode.next != pDelNode){
pNode = pNode.next;
}
pNode.next = null;
}
}
时间复杂度分析:
对于n-1个非尾部结点而言删除的时间复杂度为O(1),对于尾部结点删除而言,仍然需要O(n)的时间复杂度。但是平均时间复杂度是:[ ( n - 1 ) * O( 1 ) + O( n ) ] / n,结果还是O(1)。
测试:
public static void main(String[] args) {
ListNode ln1 = new ListNode();
ListNode ln2 = new ListNode();
ListNode ln3 = new ListNode();
ListNode ln4 = new ListNode();
ListNode ln5 = new ListNode();
ListNode ln6 = new ListNode();
ListNode ln7 = new ListNode();
ListNode ln8 = new ListNode();
ln1.next = ln2;
ln2.next = ln3;
ln3.next = ln4;
ln4.next = ln5;
ln5.next = ln6;
ln6.next = ln7;
ln7.next = ln8;
ln8.next = null;
ln1.data = 1;
ln2.data = 2;
ln3.data = 3;
ln4.data = 4;
ln5.data = 5;
ln6.data = 6;
ln7.data = 7;
ln8.data = 8;
Main m1 = new Main();
m1.deleteNode1(ln1, ln2);
while(ln1!=null){
System.out.println(ln1.data);
ln1 = ln1.next;
}
}
小结:
考查对链表的认识。