首页 > 编程语言 >算法面试之道:在O(1)的时间内删除单链接链表的指定节点

算法面试之道:在O(1)的时间内删除单链接链表的指定节点

时间:2023-06-14 11:02:27浏览次数:71  
标签:node 删除 next 链表 面试 算法 节点


对于一个单项链接的链表,给定其中某个任意节点,要求在O(1)的时间复杂度内删除该节点。表面上看起来,似乎不可能做到,因为如果要求时间复杂度是O(1)的话,那意味着,算法实现中,不得包含有任何循环或是对链表的整体遍历。

但问题在于,要删除某个指定节点,我们需要通过遍历,找到该节点的前节点,然后修改前节点的next指针,这样才能正常的删除当前节点。

但如果给定的节点不是链表的末尾节点的话,那么要做到这一点就不难,只需要一点小技巧就可以实现,于是,问题转换如下:

假设节点v是单项链接链表中的某个节点,并且确保v不是链表的尾节点,要求在O(1)的时间复杂度内删除该节点.

例如给定链表如下:

算法面试之道:在O(1)的时间内删除单链接链表的指定节点_链表

给定的节点v就是值为3的节点,要求在O(1)的时间内删除该节点,并且不能使用多余内存。

一般做法是找到节点3的前节点,也就是节点2,然后把节点2的next指针指向节点4,但由于我们不能从头遍历,所以我们无法找到节点2.

但是我们可以使用个小技巧,把节点4的值拷贝到节点3,然后把节点3的next指针指向节点5,那就可以了:

算法面试之道:在O(1)的时间内删除单链接链表的指定节点_谷歌_02

具体代码实现如下:

public class NodeDelete {

    public void deleteNode(Node node) {
        if (node.next == null) {
            return ;
        }

        node.val = node.next.val;
        node.next = node.next.next;
    }
}

主入口处的代码如下:

public class LinkList {
    public static void main(String[] args) {
        ListUtility util = new ListUtility();
        Node head = util.createList(10);
        System.out.println("Link list before node deletion:");
        util.printList(head);
        Node n = util.getNodeByIdx(head, 3);

        NodeDelete nd = new NodeDelete();
        nd.deleteNode(n);

        System.out.println("Link list after node deletion: ");
        util.printList(head);
    }
}

首先构建一个含有5个节点的单向链表,然后获得值为3的节点,先把节点删除前的链表打印出来,然后调用算法实现删除指定节点,最后再把删除后的链表打印出来,运行后结果如下:

Link list before node deletion:
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
Link list after node deletion:
0 -> 1 -> 2 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null

由此可见,我们的算法实现是正确的,同时在算法实现中,我们并没有使用循环去遍历队列,只是对节点的next指针做一些操作,因此算法的时间复杂度确实是O(1).

问题的解法看起来相当简单,但问题在于,在面试中,你处于一种紧张的压力状态之下,同时思考时间有限,有了想法后,还得把代码写出来,并且保证代码不出错,因此,看似简单的题目,在有限的时间约束和一定的心理压力之下,想顺利的解决,也不是一件容易的事情。

更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:

算法面试之道:在O(1)的时间内删除单链接链表的指定节点_算法_03


标签:node,删除,next,链表,面试,算法,节点
From: https://blog.51cto.com/u_16160261/6476239

相关文章

  • 面试算法:波浪型数组的快速排序法
    波浪型数组是具备这样特性的数组,它的元素先是递增,到达某个点后开始低贱,接着达到某个点时又递增,接着右递减,以下数组就是一个波浪型数组:A:57,131,493,294,221,339,418,452,442,190A[0]A[1]A[2]A[3]A[4]A[5]A[6],A[7],A[8],A[9]不难发现,A[0]-A[4]是一个波浪,因为......
  • 2023年 1月 Tita 升级|绩效流程节点支持签名确认
    升级快速一览:点击免费领取绩效考核模版等资料·【考核模板】绩效流程节点支持签名确认;绩效流程节点支持签名确认使用场景:考核执行过程中,在指标确认、绩效面谈、绩效结果确认节点需要执行人的签名确认,并将签名进行留存当前仅支持在指标确认、绩效面谈、绩效结果确认节......
  • 链表
    结构体结构体的首地址即为结构体第一个成员的地址,如果结构体的第一个成员是数组,则结构体的地址也是数组中第一个成员的地址链表的基础知识顺序表(比如说数组)各元素的地址是连续的。数组存储在栈区,而链表存储在堆区。图中指针也称为链,指针的类型就是结构体的名字,比如结构......
  • 数据仓管概念、关系建模和维度建模、维度表和事实表、数据仓库建模、什么是拉链表?
    目录数据仓管概念数据仓管分为5层数仓为什么要分层数据集市和数据仓库的区别数仓命名规范范式理论第一范式第二范式第三范式关系建模和维度建模星型模型:雪花模型:星座模型:模型选择:维度表和事实表数据仓库建模ODSDWD什么是拉链表?数据仓管概念数据仓管分为5层ODS原始数据层存......
  • C++面试八股文:C++中,函数的参数应该传值还是传引用?
    C++面试八股文:C++中,函数的参数应该传值还是传引用?某日二师兄参加XXX科技公司的C++工程师开发岗位第8面:面试官:C++中,函数的参数应该传值还是传引用?二师兄:要看参数的用途。如果是出参,必须传引用。如果是入参,主要考虑参数类型的大小,来决定传值还是传引用。面试官:为什么不使用......
  • C++面试八股文:什么是RAII?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第13面:面试官:什么是RAII?二师兄:RAII是ResourceAcquisitionIsInitialization的缩写。翻译成中文是资源获取即初始化。面试官:RAII有什么特点和优势?二师兄:主要的特点是,在对象初始化时获取资源,在对象析构时释放资源。这种技术可以......
  • 【基础算法】单链表的OJ练习(2) # 链表的中间结点 # 链表中倒数第k个结点 #
    前言对于单链表的OJ练习,<fontcolor=bluesize=4>需要深刻理解做题的思路</font>,这样我们才能够在任何场景都能够熟练的解答有关链表的问题。关于OJ练习(1):==->==传送门==<-==,其题目较为简单,思路也好理解,本章与(1)差不多,难度不大,<fontcolor=orangesize=4>核心点就在于理解解......
  • C++面试八股文:什么是RAII?
    某日二师兄参加XXX科技公司的C++工程师开发岗位第13面:面试官:什么是RAII?二师兄:RAII是ResourceAcquisitionIsInitialization的缩写。翻译成中文是资源获取即初始化。面试官:RAII有什么特点和优势?二师兄:主要的特点是,在对象初始化时获取资源,在对象析构时释放资源。这种技术可以......
  • #yyds干货盘点# LeetCode程序员面试金典:被围绕的区域
    题目:给你一个mxn的矩阵board,由若干字符'X'和'O',找到所有被'X'围绕的区域,并将这些区域里所有的 'O'用'X'填充。 示例1:输入:board=[["X","X","X","X"],["X","O","O",&quo......
  • Java面试笔记202306
    Java基础ArrayListArrayList底层数据是动态数组,初始长度为10,每次扩容为原来的1.5倍。扩容流程:首先会创建一个新的长度的数组,然后使用Arrays.copyOf()方法将旧的数组中的元素复制到新的数组中,最后会将新插入的数据插入到新的数组中。IO和NIO的区别io指的是io流。可以实现数......