《剑指Offer》Java刷题 NO.14 链表中倒数第K个结点

《剑指Offer》Java刷题 NO.13 调整数组顺序使奇数位于偶数之前(链表、两指针配合)

时间:2020-02-22 题目: 输入一个链表,输出该链表中倒数第k个结点。


思路: 设置两个指针,第一个先比第二个快k-1,然后两个指针一起后移,当第一个指针到尾端时,第一个指针正好在倒数第k个 注意:

  1. head是否为null
  2. k是否为0
  3. k是否大于链表总的结点数

变形:

  1. 找出链表中间结点:第一个指针正常移动(每次移动一个),第二个指针是第一个速度的2倍(每次移动两个),当第二个指针到达尾端时,第一个指针正好在中间
  2. 判断链表是不是环形链表:第一个指针正常移动(每次移动一个),第二个指针是第一个速度的2倍(每次移动两个),如果第二个指针追上了第一个指针,则是环形列表,否则第二个指针到达尾端(null),则证明不是环形列表

Java代码:

import java.util.ArrayList;

class ListNode{
          
   
    int val;
    ListNode next=null;
    ListNode(int val){
          
   
        this.val=val;
    }
    public void setNext(ListNode node){
          
   
        this.next=node;
    }
    public static void print(ListNode head){
          
   
        while(head!=null){
          
   
            System.out.println(head.val);
            head=head.next;
        }

    }
}
/**
 * 输入一个链表,输出该链表中倒数第k个结点。
 */
public class FindKthToTail {
          
   
    public static ListNode findKthToTail(ListNode head,int k){
          
   
        if(head==null||k==0) return null;
        ListNode fast=head;
        ListNode slow=head;
        while(--k>0){
          
   //需要执行k-1次,不能是k--(会执行k次)
            if(fast.next==null) return null;//说明k比总结点数还大
            fast=fast.next;
        }
        while(fast.next!=null) {
          
   
            slow=slow.next;
            fast=fast.next;
        }
        return slow;
        //大神超简洁代码
        /*for(;fast.next!=null;fast=fast.next){
            if(--k<=0) slow=slow.next;
        }
        return k>1?null:slow;*/
    }

    /**
     *找出链表中间结点
     */

    public static ListNode findMidNode(ListNode head){
          
   
        if(head==null) return null;
        ListNode slow=head;
        ListNode fast=head;
        while(fast.next.next!=null){
          
   
            //因为2N/2=N;(2N+1)/2=N,所以只有当fast.next.next!=null时才把slow指针往后移一个
            slow=slow.next;
            fast=fast.next.next;
        }
        return slow;
    }

    /**
     *判断链表是不是环形链表
     */
    public static boolean isLoopList(ListNode head){
          
   
        if(head==null) return false;
        ListNode slow=head;
        ListNode fast=head;
        while(fast.next.next!=null){
          
   
            //因为2N/2=N;(2N+1)/2=N,所以只有当fast.next.next!=null时才把slow指针往后移一个
            slow=slow.next;
            fast=fast.next.next;
            if(fast==slow) break;
        }
        return fast==slow?true:false;
    }

    public static void main(String[] args) {
          
   
         ListNode head = new ListNode(0);
        ListNode p = head;
        for (int i = 0; i < 5; i++) {
          
   
            ListNode newnode = new ListNode(i + 1);
            p.next = newnode;
            p = p.next;
        }
        p = head;
       //head.print(p);
      //System.out.println(findMidNode(p).val);
        //System.out.println(isLoopList(heapd));
        ListNode.print(reverse(p));
    }
}
经验分享 程序员 微信小程序 职场和发展