1、找到链表倒数第n个节点
代码思路:使用两个指针,一个指向链表的头(begin),另一个指向链表的第n个节点(end),在这里暂且叫begin和end,当end到达最后一个元素的时候,begin刚好到达倒数第n个元素。
需要注意的点:
end指针到达第n个节点不代表要走n步,而是n-1步。例如链表(123456)的倒数第3个节点,begin在 1 这个位置,end要在 3 这个位置,走两步。
// 求链表倒数第n个节点的值
private static<T> T reciprocal(LinkList plist, int n){
if(plist == null || n <= 0){
return null;
}
//plist = plist.getNext();
LinkList begin = plist.getNext();
LinkList end = plist.getNext();
int count = 0;
// 先把end放在第n个
while( end.getNext() != null && count != (n - 1)){
end = end.getNext();
count ++;
}
while(end.getNext() != null){
begin = begin.getNext();
end = end.getNext();
if(end.getNext() == null){
return (T) begin.getData();
}
}
return null;
}
2、找到链表的中间节点
代码思路:使用两个指针,一个指针一次走一步(慢指针slow),一个指针一次走两步(快指针quick),当快指针走到最后的节点时,慢指针刚好走到链表的中间。
需要注意的点:
quick指针走两步,容易越界,需要判断quick.next.next是否为空。
// 求链表的中间node
public static<T> T findLinkMidNode(LinkList plist){
if(plist == null){
return null;
}
LinkList slow = plist.getNext();
LinkList quick = plist.getNext();
// quick走到底,说明slow走到中间了
while(quick.getNext() != null){
// 走到只剩一个的时候,slow和quick各走一步
quick = quick.getNext();
if(quick.getNext() != null){
quick = quick.getNext();
}
slow = slow.getNext();
}
return (T) slow.getData();
}
3、判断链表是否有环(是否是环形链表)
代码思路:使用两个指针,一个指针一次走一步(慢指针slow),一个指针一次走两步(快指针quick),当快指针=慢指针时,代码这两个指针相遇,也代表链表有环。
需要注意的点:
之前的链表没有环,退出循环的条件都是p.next != null,所以这次要确定好退出循环的条件,不要在环里死循环
// 环形链表
public static boolean isRoundLinkList(LinkList plist){
if(plist == null){
return false;
}
LinkList slow = plist.getNext();
LinkList quick = plist.getNext();
while(quick.getNext().getNext() != null){
slow = slow.getNext();
quick = quick.getNext().getNext();
if(slow == quick){
return true;
}
}
return false;
}