实现这个算法,可以用递归和非递归。因为单向链表只能向后遍历,所以一般会想到用递归这种方法,然后当递归遍历到链表末端时,该方法会回传一个置为0的计数器。
之后的每一次调用都会将这个计数器加1,当计数器等于K时,表示我们访问的是链表倒数第K个元素。
方法A
- public static int nToLast(LinkedListNode head,int k){
- if(head==null){
- return 0;
- }
- int i = nToLast(head.next,k)+1;//当遍历到最后一个元素时,计数器i开始自增。
- if(i==k){
- System.out.println(head.data);
- }
- return i;
- }
但是这个方法只能打印倒数第K个值,不能返回该元素,因为我们无法用一般的返回语句回传一个结点和一个计数器。
用一个简单的类包装计数器值,就可以模仿按引用传值。
- public class MyCount
- {
- public int value = 0;
- }
- LinkedListNode nToLast(LinkedListNode head,int k,MyCount i){
- LinkedListNode node = nToList(head.next,k,i);
- i.value = i.value+1;
- if(i.value == k){
- return head;
- }
- return node;
- }
迭代法,一个更直接的方法,我们可以使用两个指针p1和p2,并将他们指向链表中相距k个结点的两个结点,具体做法是将p1和p2指向链表首结点,然后将 p2向后移动k个结点,之后,我们以相同的速度移动这两个指针,p2会在移动length-k步后抵达链表末尾结点,这时,p1就指向链表倒数第k个结 点。
- LinkedListNode nToList(LinkedListNode head,int k){
- if(k<=0)
- return null;
- LinkedListNode p1 = head;
- LinkedListNode p2 = head;
- for(int i=0;i<k-1;i++){
- if(p2==null)
- return null;
- p2 = p2.next;
- }
- if(p2==null)
- return null;
- while(p2.next!=null){
- p1 = p1.next;
- p2 = p2.next;
- }
- return p1;
- }
或者
- class Node{
- Node(int value, Node nnode){
- this.value=value;
- this.nnode=nnode;
- }
- }
- public static Node findknode(Node head, int k){
- if ((Null==head) || (Null==head.nnode))
- return head;
- cur=head;
- knode=head;
- nextnode=Null;
- count=0;
- while(cur!=Null){
- count+=1;
- if(count>=k){
- nextnode=knode.nnode;
- knode=nextnode;
- }
- nextnode=cur.nnode;
- cur=nextnode;
- }
- return knode;
- }