在O(1)时间内删除链表结点
题目一
在给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。
思路
本题缺陷,要求O(1)时间删除,相当于隐藏了一个假设:待删除的节点的确在链表中。
在单向链表中,节点没有指向前一个节点的指针,所以只好从链表的链表的头结点开始顺序查找。这样的时间复杂度为O(n),要在O(1)的时间删除节点,可以这样实现:
将待删除节点的next节点 j 的值赋值给 i ,再把 i 的指针指向 j 的下一个节点,最后删除 j ,效果等同于删除 j 。
全面考虑其他情况:
- 待删除节点i为尾节点是,无下一个节点,只能从头开始遍历到尾节点;
- 链表中只有一个节点时(即是头结点,又是尾节点),必须把头结点也设置为null;
测试用例
功能测试 (多个节点链表,删除头结点、中间节点和尾节点;单个节点链表)
特殊测试 (头结点或者删除节点为null)
java代码
1 | /** |
总结
- 链表中删除节点的方法中,虽然直接令 head=null, 但是在主函数中的head还是不变的,因此要令删除节点的返回值为LinkNode,将返回值赋值给主函数中的head,这样才能实现真正的删除。
- 另一种情况可以令删除函数返回值为void,只是需要定义一个头结点head(1中的head相当于第一个节点),这个头结点中不存任何数据,仅仅起到执政的作用,第一个节点是头结点的下一个节点,通过对head.next操作,能够实现真正的删除。
- 和链表有关的特殊情况:头结点、尾节点,链表仅有一个节点,null等。
删除链表中的重复节点
题目二
在一个排序的链表中,如何删除重复的节点?
思路
设置一个 pre ,用于记录当前节点的前一个节点,再设置一个布尔变量 needDelete ,如果说当前节点和后一结点的值相同(记该值为dupVal),needDelete赋值为真。
当 needDelete 为真时,通过寻魂往后找到第一个不为 dupVal 的节点,把该节点设置为当前节点,并赋值给 pre.next, 即相当于完成了删除操作;而当 needDelete 为假时,把当前节点和 pre 往后移一位即可。
测试用例
- 功能测试(重复的节点位于链表的头部、中间、尾部;链表中无重复节点)
- 特殊输入测试(头结点为null、所有节点都重复)
java代码
1 | /** |
总结
- 删除多个节点时,只需要把重复节点前一个节点的next指向重复节点的后一个节点;
- 不要把重复节点一个一个删除,先定义一个布尔变量确定当前节点是否重复,然后按1 中的方法删除即可。