一、给定一个链表,返回链表开始入环的第一个结点,如果链表没有环返回null
思路:定义两个节点fast和slow,fast每次走两步,slow走一步,如果fast和slow相遇,则说明链表有环。
如果有环,则说明(X表示起点到环的起点的距离,L表示环的起点到相遇位置的距离,C表示一圈的长度)
1.fast所走的路程是slow的二倍。
2.slow所走的路程是X + L。
3.fast所走的路程是X + L + C。
可以推导出 2(X+L) = X + L +C,即X = C - L。
当他们相遇时,将slow返回到链表的起始位置,然后让fast和slow各走一步,当他们再次相遇时,就是进入环的位置
public Node isCycle(){
Node fast = this.head;
Node slow = this.head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(slow == fast){
break;
}
}
if(fast == null || fast.next ==null){
return null;
}
slow = this.head;
while(slow != fast){
fast = fast.next;
slow = slow.next;
}
return slow;
}
二、删除所有重复的结点
思路:定义一个虚拟结点,然后定义一个temp结点保存虚拟结点,再定义一个cur结点遍历链表
public Node del(){
Node newHead = new Node(0);
Node temp = newHead;
Node cur = this.head;
while(cur != null){
if(cur.next != null && cur.data == cur.next.data){
while(cur.next != null && cur.data == cur.next.data){
cur = cur.next;
}
cur = cur.next;
}
else{
temp.next = cur;
temp = cur;
cur = cur.next;
}
}
temp.next = null;
return newHead.next;
}
三、链表的回文结构
思路:1.将链表翻转一半。
(找链表一半的方法:定义两个结点fast和slow,让fast走两步,slow走一步,放fast.next是null时,slow所指的就是中间位置)
2.判断data值是否相同,一个从前往后,一个从后往前,知道两个相遇
public boolean checkPalindrome(){
if(this.head == null){
return false;
}
if(this.head.next == null){
return true;
}
//找到中间结点
Node fast = this.head;
Node slow = this.head;
Node cur = this.head;
Node curNext = this.head;
while(fast.next != null && fast != null){
fast = fast.next.next;
slow = slow.next;
}
//翻转
cur = slow.next;
curNext = cur.next;
while(cur != null) {
cur.next = slow;
slow = cur;
cur = curNext;
}
//判断
while(this.head != slow){
if(this.head.data != slow.data){
return false;
}
if(this.head.next == slow){//实现偶数结点
return true;
}
this.head = this.head.next;
slow = slow.next;
}
return true;
}