7.判断环的入口结点
第一次第二次看感觉都无从下手,还是看了题解,主要思路是:
假设前面无环的结点有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)的空间复杂度,不符合要求
8.输出倒数第k个结点
让快指针先走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 here
ListNode 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;
}
}
}