18.1 在 O(1) 时间内删除链表节点
题目描述
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。
解题思路
① 如果该节点不是尾节点,那么可以直接将下一个节点的值赋给该节点,然后令该节点指向下下个节点,再删除下一个节点,时间复杂度为 O(1)。
② 否则,就需要先遍历链表,找到节点的前一个节点,然后让前一个节点指向 null,时间复杂度为 O(N)。
综上,如果进行 N 次操作,那么大约需要操作节点的次数为 N-1+N=2N-1,其中 N-1 表示 N-1 个不是尾节点的每个节点以 O(1) 的时间复杂度操作节点的总次数,N 表示 1 个尾节点以 O(N) 的时间复杂度操作节点的总次数。(2N-1)/N ~ 2,因此该算法的平均时间复杂度为 O(1)。
测试用例
功能测试(多个结点链表,删除头结点、中间结点和尾结点;单个结点链表)
特殊测试(头结点或删除结点为null)
package 剑指offer.在O时间内删除链表节点;/*
作者 :XiangLin
创建时间 :03/04/2020 20:08
文件 :Offer18_01.java
IDE :IntelliJ IDEA
*/
public class Offer18_01 {
static class ListNode{
public int value;
public ListNode next;
public ListNode(){
}
public ListNode(int value,ListNode next){
this.value = value;
this.next = next;
}
}
public static void main(String[] args) {
System.out.println("****功能测试***");
test1();
System.out.println("***仅有一个节点元素的单链表测试***");
test2();
System.out.println("***特殊输入测试****");
test3();
}
public static ListNode deleteNodeInList(ListNode phead,ListNode pdelNode){
return Soluton1(phead,pdelNode);
}
/**
* 如果要删除的节点是中间节点,我们可以直接将它后面的一个节点的值赋给它, 而要删除的节点就变成了它后面的一个节点,
* 要考虑删除节点是尾结点,和链表中只有一个节点的情况
*
* @param phead
* @param pdelNode
* @return
*/
private static ListNode Soluton1(ListNode phead, ListNode pdelNode) {
if (phead == null || pdelNode == null){
return phead;
}
if (pdelNode.next != null){// 要删除的节点在链表中间位置
ListNode p = pdelNode.next;
pdelNode.value = p.value; //注意顺序不能错
pdelNode.next = p.next;
p = null;
}else if (phead.next == pdelNode){// 链表只有一个结点
phead.next = pdelNode.next;
pdelNode = null;
}else {
ListNode p = phead;
while (p.next != pdelNode){
p = p.next;
}
p.next = pdelNode.next;
pdelNode = null;
}
return phead;
}
/**
* 功能测试
*/
private static void test1(){
System.out.println("(不加头结点)有三个节点元素的单链表");
ListNode node3 = new ListNode(9,null);
ListNode node2 = new ListNode(2,node3);
ListNode node1 = new ListNode(4, node2);
ListNode pHead = new ListNode(-1, node1);// 头结点
System.out.println("删除之前");
printListNode(pHead);
System.out.println("删除之后--->");
deleteNodeInList(pHead, node2);
printListNode(pHead);
}
private static void test2() {//
System.out.println("(不加头结点)仅有一个节点元素的单链表");
ListNode node1 = new ListNode(4, null);
ListNode pHead = new ListNode(-1, node1);// 头结点
System.out.println("删除之前");
printListNode(pHead);
System.out.println("删除之后-->");
deleteNodeInList(pHead, node1);
printListNode(pHead);
}
/**
* 特殊输入测试
*/
private static void test3() {//
System.out.println("(不加头结点)有三个节点元素的单链表");
ListNode node3 = new ListNode(9, null);
ListNode node2 = new ListNode(2, node3);
ListNode node1 = new ListNode(4, node2);
ListNode pHead = new ListNode(-1, node1);// 头结点
System.out.println("删除之前");
printListNode(pHead);
System.out.println("删除之后(传入参数为null,null)--->");
deleteNodeInList(null, null);
printListNode(pHead);
}
/**
* 打印链表
*
* @param pHead
*/
private static void printListNode(ListNode pHead) {
ListNode p = pHead.next;
while (p != null){
System.out.print(p.value + " ");
p = p.next;
}
System.out.println();
}
}
所有巧合的是要么是上天注定要么是一个人偷偷的在努力。
公众号,关注回复【电子书】有惊喜,资源多多。
个人微信公众号,专注于学习资源、笔记分享,欢迎关注。我们一起成长,一起学习。一直纯真着,善良着,温情地热爱生活,,如果觉得有点用的话,请不要吝啬你手中点赞的权力,谢谢我亲爱的读者朋友。
The only person you need to compare yourself to is who you have been. The only person you need to be better than is who you are.
你需要跟自己比的唯一一个人,就是曾经的自己。你需要比一个人变得更好,那个人就是现在的你。
给大家推荐一个Github,上面非常非常多的干货,保证让你满意:https://github.com/XiangLinPro/IT_book
2020年4月3日于重庆城口
好好学习,天天向上,终有所获