前言
今天做了一道关于链表的题目,题目本身非常简单,但是其中需要注意的一些细节很值得探讨,也让我注意到写代码过程中代码的鲁棒性问题。根据题目写出正确的解法是基础要求,能够进一步考虑到一些细节,排除潜在的崩溃风险,则是锦上添花。
剑指Offer 22 链表中倒数第K个节点
题目详情
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
示例:给定一个链表: 1->2->3->4->5, 和 k = 2.返回链表 4->5.
来源:力扣(LeetCode)
题解
题目本身非常的简单,使用双指针便可以轻松解决,这样只需要遍历整个链表一次便可以得到题目要求的倒数第K个节点。根据这样的思路,可以给出基础的算法:
public class Offer22 {
//有缺陷的代码
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode left = head;
ListNode right = head;
while (k > 0) {
right = right.next;
--k;
}
while (right != null) {
right =right.next;
left = left.next;
}
return left;
}
}
总体上来说这个算法的思路是正确的,但是里面有一些小细节需要注意:
-
空指针异常
当然Java中并没有指针的概念,但是如果这道题使用C/C++进行解答的话,就需要考虑如果head给的是一个空指针的情况。 -
链表节点数量少于k 这主要是针对代码中第一个while循环,假设k大于链表的长度,右指针在指向到链表结尾时不会停下,仍会继续尝试寻找下一个节点,因此需要对此加以限制和判断。
考虑到这些问题以后,我们可以对代码进行进一步完善:
public class Offer22 {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode left = head;
ListNode right = head;
while (k > 0 && right != null) {
//增加对k大于链表节点总数的判断
right = right.next;
--k;
}
while (right != null) {
right =right.next;
left = left.next;
}
return left;
}
}
因为k=0和输入为空的情况在这道题里没有实际意义,同时官方题目也没有给出k的限制,因此没有做进一步的处理,但是从代码的角度来说,以上的问题都是需要去考虑的和处理的。
总结
暂时没什么好写的,等以后遇到新的题目再进行补充吧。