在O(1)的时间内删除结点
程序员文章站
2024-03-21 20:47:46
...
剑指Offer_13: 在的时间内删除结点
2018/05/14 星期一
题目: 给定单项链表的头指针和一个结点指针,定义一个函数在的时间删除该结点。链表结点和函数的定义如下:
class ListNode { int data; ListNode nextNode; } public void deleteNode(ListNode head, ListNode deListNode)
思考三分钟。。。。
在单链表中删除一个结点,最简单的方法无疑就是从链表的头结点开始,顺序遍历查找要删除的结点,并在链表中删除该结点。
- 上图(a)中表示一个单链表
- 上图(b)中,表示顺序遍历删除i结点。删除i结点之前,先从头结点开始遍历到i前面的一个结点h,然后把h结点的指针指向i的下一个节点j,再删除节点i(常规思路复杂度)。
- 上图(c)中,把结点j中的内容复制到结点i中,再把i中的指针指向节点j的指针。这种方法不用遍历i结点前面的元素。时间复杂度为
基于图(c)的思路中还需要考虑一个问题,如果更新的节点位于链表的尾部(尾结点),怎么办,它没有下一个节点?这时候只能通过顺序遍历查找(图(b)中表示的方法)。如果我们有一个节点,删除的位置即是头结点也是尾结点,当我们在删除的时候除了删除节点还是将头结点置为null。完整代码如下:
public void deleteNode(ListNode head, ListNode deListNode) {
if (deListNode == null || head == null) {
return;
}
// 如果删除头结点
if (head == deListNode) {
head = null;
} else {
// 如果删除结点为尾结点
if (deListNode.nextNode == null) {
ListNode pointListNode = head;
while (pointListNode.nextNode.nextNode != null) {
pointListNode = pointListNode.nextNode;
}
pointListNode.nextNode = null;
} else {
deListNode.data = deListNode.nextNode.data;
deListNode.nextNode = deListNode.nextNode.nextNode;
}
}
}
算法的时间复杂度:对于n-1个非尾结点而言,我们是可以在的时间内完成操作;对于尾结点我们仍然需要顺序查找,时间复杂度为。总的平均时间复杂度是,结果还是。
上述的代码并不是完美的代码,它基于一个假设,那就是要删除的结点存在链表当中。
测试用例:
- 功能测试:删除多个结点链表的中间结点,头结点,尾结点等;从只有一个结点的链表中删除唯一结点。
- 特殊输入测试:
推荐阅读
-
在O(1)的时间内删除结点
-
在带头结点的单链表L中,删除所有值为x的结点,并释放其空间,假设值为x的结点不唯一,试编写算法以实现上述操作
-
线性表的链式存储结构:定义、单链表存储结构、给链表头结点分配空间、初始化链表数据、输出链表、在某个位置上插入数据、头插法、尾插法、删除某个位置上的数据、删除某个数据、删除整个链表计算链表的长度
-
我们在删除SQL Sever某个数据库表中数据的时候,希望ID重新从1开始,而不是紧跟着最后一个ID开始需要的命令
-
剑指offer56:删除链表中重复的结点,排序的链表中,删除重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
-
我们在删除SQL Sever某个数据库表中数据的时候,希望ID重新从1开始,而不是紧跟着最后一个ID开始需要的命令_MySQL
-
我们在删除SQL Sever某个数据库表中数据的时候,希望ID重新从1开始,而不是紧跟着最后一个ID开始需要的命令_MySQL
-
我们在删除SQL Sever某个数据库表中数据的时候,希望ID重新从1开始,而不是紧跟着最后一个ID开始需要的命令
-
在不到5分钟的时间内,在5个云服务器的群集上运行1,000个Docker Redis容器,每个服务器具有2GB的内存...
-
剑指offer56:删除链表中重复的结点,排序的链表中,删除重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5