
第一次第二次看感觉都无从下手,还是看了题解,主要思路是:
假设前面无环的结点有a个,环有b个结点,则设置快慢结点之后,fast结点一次走两步,slow结点一次走一步。则相遇时fast结点总步长f,slow结点总步长s满足:
f = 2 * s;
f - s = kb;
则s = kb,f=2kb.
我们要找的入口结点在a+kb;因此只要让slow再走a步即可,怎么做呢?只要让第一次相遇后,fast结点从头结点开始一次一步往后走,两者再次相遇的地方就是入口结点
/*public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}
*/
public class Solution {public ListNode EntryNodeOfLoop(ListNode pHead) {ListNode fast = pHead;ListNode slow = pHead;int flag =0;while(fast!=null && fast.next!=null && fast.next.next!=null){fast = fast.next.next;slow =slow.next;if(fast==slow){flag = 1;break;}}if(flag==0) return null; //无环else{//一定有环fast = pHead;while(true){if(slow==fast) return slow; //一定要先判断!!,否则在a=0的时候就会出错fast = fast.next;slow = slow.next;}}}
}
双指针的做法空间复杂度为1,否则用set需要O(N)的空间复杂度,不符合要求

让快指针先走k-1步,当快指针到尾部时,慢指针就是倒数第k个。用双指针,空间复杂度为1,时间复杂度为o(N)
import java.util.*;/** public class ListNode {* int val;* ListNode next = null;* public ListNode(int val) {* this.val = val;* }* }*/public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param pHead ListNode类 * @param k int整型 * @return ListNode类*/public ListNode FindKthToTail (ListNode pHead, int k) {// write code hereListNode right = pHead, left = right;int count = k-1;while(count!=0){//让右边结点先走k-1步if(right==null||right.next==null) return null; //说明链表长度比k小right = right.next;count --;}while(true){if(right.next==null) return left;//当右边结点到尾部时,左边结点就是倒数第k个left = left.next;right = right.next;}}
}
下一篇:相差无几成语