输入一个单向链表,输出该链表中倒数第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; }