- 判断单链表是否有环
算法思路:判断单链表是否有环,可以定义一个fast引用和一个slow引用;fast引用一次走两步,而slow引用一次走一步,当fast引用与slow引用相遇时,说明该单链表有环。
public boolean isLoop(){
Node slow = head;
Node fast = head;
while(slow != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(fast == slow){
return true;
}
}
return false;
}
2.单链表有环,输出入口节点
算法思路:
public Node findStart(){
Node q = head;
Node p = head;
while(q != null && p.next != null){
q = q.next;
p = p.next.next;
if(p == q){//找到相遇节点
p = head;
while(p != q){
p = p.next;
q = q.next;
}
return p;
}
}
return null;
}
我们发现1,2中找相遇节点的代码是重复的,可以简化第2个问题:将1中的返回类型改为Node,2中直接调用1即可。代码如下:
public Node findStart() {
Node q = isLoop();
Node p = head;
p = head;
while (p != q) {
p = p.next;
q = q.next;
}
return p;
}
3、找到单链表的倒数第k个节点,并输出。
算法思路:通过观察,我们可以得知:倒数第k个节点位置可由单链表的长度减去对应节点的顺位数得到。
public void getBackNode(int k){
int count = 0;
Node p = head;
for(p = head;p.next != null;p = p.next){
count++;
if(getLength()-count == k){//找倒数第k个节点
System.out.print(p.value);
}
}
}
上述代码还有计算长度的方法,如下:
public int getLength(){
Node p = head;
int length = 0;
while(p.next != null){
length++;
p = p.next;
}
return length;
}
4、单链表的逆置
算法思路:
当单链表只有头节点或只有两个节点时,不需要逆置。而当单链表有两个及以上的元素时,将从第1个元素断开,令它的next为空,依次访问第2个元素到第n个元素,当访问到其中的任意一个元素时,将它插入到头结点之后,也就是把它插入到第1个位置,这样原始的第1个元素就会被后面的n-1个元素插入到它的前面,原始的第2个元素就会被后面的n-2个元素插入到它的前面,…直到原始的第n个元素插入到第1个位置。这样就实现了带头结点的单链表的就地逆置。
public void reverse(){
Node p=head;
if(p == null||p.next == null||p.next.next == null){//逆置至少有两个及以上元素
return;
}
Node q = p.next.next;//保存链表的第二个元素
p.next.next = null;
while(q != null){
Node s = q.next;
q.next = p.next;
p.next = q;
q = s;//插入后继续访问后面的节点
}
}