题目17:删除链表的节点
题目描述:
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。
解题思路:
- 常规做法是从链表崔奥迪头结点开始,顺序遍查找要删除的节点,并在链表中删除该节点;时间复杂度(O(n));
- 若把下一个节点的内容复制到要删除的节点上覆盖原有的内容,在把下一个节点删除,就是相当于把当前需要删除的节点删除了?
- 问题1:如果要删除的节点位于链表的尾部,那么它就没有下一个节点,仍然从链表的头部开始,顺序遍历得到该节点的前序节点,并完成删除;
- 问题2:如果链表中只有一个节点,而我们需要删除链表的头结点(也就是尾结点),那么我们在删除节点后,还需要把链表的头节点设置为null;
代码实现:
package swordToOffer;
public class Num17_DeleteListNode {
static class ListNode{
int val;
ListNode next;
public ListNode(int value,ListNode nextNode) {
val = value;
next = nextNode;
}
}
public static ListNode deletedNode(ListNode pListNode,ListNode pToDeleted) {
if(pListNode==null||pToDeleted==null) {
return pListNode;
}
//待删除节点不是尾结点
if(pToDeleted.next!=null) {
ListNode nextNode = pToDeleted.next;
pToDeleted.val = nextNode.val;
pToDeleted.next = nextNode.next;
nextNode = null;
}else if(pListNode == pToDeleted) {//只有一个节点
pToDeleted = null;
pListNode = null;
}else { //链表包含多个节点 删除尾结点
ListNode preNode = pListNode;
while(preNode.next!=pToDeleted&&preNode!=null) {
preNode = preNode.next;
}
if(preNode==null) {
System.out.println("无法找到待删除节点!");
return pListNode;
}
preNode.next =null;
pToDeleted = null;
}
return pListNode;
}
public static void showListNode(ListNode head,ListNode PToBeDelete) {
System.out.println("============");
System.out.print("The original list is: ");
ListNode curr=head;
if(curr!=null) {
while(curr.next!=null) {
System.out.print(curr.val+",");
curr=curr.next;
}
System.out.println(curr.val);
}else {
System.out.println();
}
System.out.print("The node to be deleted is: ");
if(PToBeDelete!=null)
System.out.println(PToBeDelete.val);
else
System.out.println();
curr=deletedNode(head, PToBeDelete);
System.out.print("The result list is: ");
if(curr!=null) {
while(curr.next!=null) {
System.out.print(curr.val+",");
curr=curr.next;
}
System.out.println(curr.val);
}else {
System.out.println();
}
System.out.println("============");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ListNode p4=new ListNode(4, null);
ListNode p3=new ListNode(3, p4);
ListNode p2=new ListNode(2, p3);
ListNode p1=new ListNode(1, p2);
//删除头节点
showListNode(p1,p1);
p1=new ListNode(1, p2);
//删除中间节点
showListNode(p1,p3);
p3=new ListNode(3, p4);
p2.next = p3;
//删除尾结点
showListNode(p1,p4);
//只有一个节点的链表
ListNode p5=new ListNode(5,null);
showListNode(p5,p5);
//删除空节点
showListNode(null,null);
}
}
本题考点:
- 删除一个节点的时候,不一定需要删除节点本身,只需要把下一个节点的内容复制出来覆盖上一个节点本身,然后把下一个节点删除就行
- 考虑问题的全面性,删除节点位于头部、尾部、只有一个节点、空节点的情况
上面的时间复杂度对于非n-1节点,需要O(1) 对于尾结点O(n),总[(n-2)*O(1)+O(n)]/n =O(1)