一、判断两个链表是否有环
快的一次走两步,慢的走一步,两个相遇说明有环
public boolean isContainsRing(ListNode head) {
if (head == null) {
return false;
}
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
return true;
}
}
return false;
}
二、找环的入口节点
快的一次走两步,慢的走一步,两个相遇,
相遇的点开始走 一个从head走 两个相遇即为入口节点
public ListNode getRingEntrance(ListNode head) {
if (head == null) {
return null;
}
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
ListNode cur = head;
while (fast != cur) {
cur = cur.next;
fast = fast.next;
}
return cur;
}
}
return null;
}
三、判断链表回文结构
快的一次走两步,慢的走一步,然后从慢的所在位置入栈,然后从head去和栈中元素比较
public boolean isReverse(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
Stack<Integer> stack = new Stack<>();
while (slow != null) {
stack.push(slow.val);
slow = slow.next;
}
ListNode cur = head;
while (!stack.isEmpty()) {
if (cur.val != stack.pop()) {
return false;
}
cur = cur.next;
}
return true;
}
四、删除链表的倒数第n个节点
先让快的走n步,如果快的为null说明要删除第一个节点
然后一起走,slow.next = slow.next.next;
public ListNode deleteKth(ListNode head, int k) {
ListNode fast = head;
ListNode slow = head;
for (int i = 0; i < k; i++) {
fast = fast.next;
}
if (fast == null) {
return head.next;
}
//不能让最后一个节点指向最后一个节点的下一个 所以是fast.next != null
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return head;
}
五、逆置链表
新建一个节点,遍历原链表做头插操作
public ListNode reverseList(ListNode head) {
ListNode newHead = null;
ListNode cur = head;
while (cur != null) {
ListNode next = cur.next;
cur.next = newHead;
newHead = cur;
cur = next;
}
return newHead;
}