剑指offer第二版-23.链表中环的入口节点

本系列导航:剑指offer(第二版)java实现导航帖

面试题23:链表中环的入口节点

题目要求:
假设一个链表中包含环,请找出入口节点。若没有环则返回null。

解题思路:
当然可以使用遍历。顺序访问,当第二次访问同一个节点时,那么那个节点就是入口节点。不过这种解法需要o(n)的空间。
能不能把空间降为o(1),时间依旧为o(n)。当然可以。这种解法的思路是:首先申请两个指针,快指针一次前进两步,慢指针一次前进一步,初始化都再链表头部。然后开始移动,如果他们指向了同一个节点,则证明有环,否则没环。当他们指向了同一个节点时,慢指针再次初始化,指向头结点。快慢指针前进步数都改为1,当他们再次指向同一个节点,这个节点就是环的入口节点。不明白的话请先看证明过程链接,然后再看我说的思路总结。

这3道连续的链表题目,解法上有一定的相似性,都是使用两个指针。碰到链表或者数组的问题,没有好的解法时可以试试这几个常见思路。

解法 题目 链接
左右指针 使数组中奇数位于偶数前面/快排 链接
前后指针 链表中倒数第k个节点 链接
快慢指针 链表中环的入口节点 链接
package structure;
/**
 * Created by ryder on 2017/6/13.
 */
public class ListNode<T> {
    public T val;
    public ListNode<T> next;
    public ListNode(T val){
        this.val = val;
        this.next = null;
    }
    @Override
    public String toString() {
        StringBuilder ret = new StringBuilder();
        ret.append("[");
        for(ListNode cur = this;;cur=cur.next){
            if(cur==null){
                ret.deleteCharAt(ret.lastIndexOf(" "));
                ret.deleteCharAt(ret.lastIndexOf(","));
                break;
            }
            ret.append(cur.val);
            ret.append(", ");
        }
        ret.append("]");
        return ret.toString();
    }
}
package chapter3;
import structure.ListNode;
/**
 * Created by ryder on 2017/7/14.
 * 链表中倒数第k个节点
 */
public class P134_KthNodeFromEnd {
    public static ListNode<Integer> findKthToTail(ListNode<Integer> head,int k){
        if(head==null||k<=0)
            return null;
        ListNode<Integer> slow=head,fast=head;
        for(int i=0;i<k;i++){
            //i==k-1,第三个测试例通不过
            if(fast.next!=null || i==k-1)
                fast = fast.next;
            else
                return null;
        }
        while(fast!=null){
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }
    public static void main(String[] args){
        ListNode<Integer> head = new ListNode<>(1);
        head.next= new ListNode<>(2);
        head.next.next = new ListNode<>(3);
        System.out.println(findKthToTail(head,1).val);
        System.out.println(findKthToTail(head,2).val);
        System.out.println(findKthToTail(head,3).val);
        System.out.println(findKthToTail(head,4));
    }
}

运行结果

3
2
1
null

推荐阅读更多精彩内容