输入一个单向链表,输出该链表中倒数第k个结点。
思路一:首先我们可以想到的是遍历完整个链表然后从尾部回溯k个节点就能找到,但是单向链表不能从尾部向前遍历。这时,我们就可以想到先遍历一遍计算出总共的结点个数count,然后再从头部开始遍历到count-k,就能取到倒数第k个结点了。这个方法之间复杂度虽然为O(n),但是遍历了两次链表,对于结点个数不多的链表来说适用,但是数据量太大的话就比较影响效率了。
测试代码:
public T find(int k){
int count = 0;//统计结点个数
Entry<T> cur = this.head;
while (this.head != null){
count++;
cur = cur.next;
}
for (int i = 0; i <= count - k ; i++) {
cur = cur.next;
}
return cur.data;
}
思路二:为了在数据量较大的情况下不影响效率,这时我们应该想到怎么样遍历一次链表就取到要找的值。这时我们可以想到利用快慢指针可以达到目的。定义两个指针,慢指针比快指针慢上k个结点,这样当快指针遍历到尾部时,慢指针就刚好指向倒数第k个结点。这样很好的提高了效率,只遍历了一次链表。
测试代码:
public T find(int k){
Entry<T> fast = this.head;
Entry<T> slow = this.head.next;
for (int i = 0; i < k; i++) {//先让快指针指向正数第k个结点
fast = fast.next;
if (fast == null){//如果链表长度小于k
return null;
}
}
while (fast.next != null){//当快指针走到尾部时,慢指针刚好指向倒数第k个结点
fast = fast.next;
slow = slow.next;
}
return slow.data;
}
本文介绍了两种高效查找单向链表中倒数第k个结点的方法:一是通过两次遍历计算结点总数再定位;二是采用快慢指针技巧仅需遍历一次链表。
1113

被折叠的 条评论
为什么被折叠?



