1. 判断链表中是否有环
/**
* 判断链表中是否有环
* 通过快慢指针法
* 思路: 快指针一次两步, 慢指针一次一步,
* 如果链表中没有环, 快指针会到达尾节点, 如果链表中有环, 两指针会相遇
* 空间复杂度O(1), 时间复杂度O(n)
* @return
*/
public static boolean isCircle(Node node) {
//快慢指针
Node fast = node;
Node slow = node;
//如果链表中有环, 快慢指针终将相遇, 否则将会到链表的末端
while ((fast = fast.getNext()) != null && fast != slow) {
fast = fast.getNext();
if (fast == null) {
return false;
} else if (fast == slow) {
return true;
} else {
slow = slow.getNext();
}
}
return fast == slow;
}
2. 两个有序链表的合并
/**
* 两个有序链表的合并(正序)
* 空间复杂度O(1), 时间复杂度O(m+n)
*/
public static Node combine(Node node1, Node node2) {
Node first = new Node();
Node item = first;
while (node1 != null && node2 != null) {
if (node1.getValue() <= node2.getValue()) {
item.setNext(node1);
item = node1;
node1 = node1.getNext();
} else {
item.setNext(node2);
item = node2;
node2 = node2.getNext();
}
}
return first.getNext();
}
3. 删除链表倒数第n个节点
/**
* 删除链表倒数第n个节点
* 思路1: 拿一个数组记录所有节点, 然后删除这个节点 (空间复杂度O(n), 时间复杂度O(n))
* 思路2: 一边遍历一遍反转链表, 再反向遍历, 删除这个节点同时将链表复原 (空间复杂度O(1), 时间复杂度O(n))
*/
public static Node deleteNode(Node node, int inverseIndex) {
//第一次遍历, 反转链表
Node last = null;
Node item = node;
Node next = item.getNext();
while (next != null) {
item.setNext(last);
last = item;
item = next;
next = next.getNext();
}
item.setNext(last);
//从最后一个节点(item)开始, 准备删除倒数第inverseIndex个节点
next = last;
last = null;
int i = 1;
while (next != null) {
//加入删除节点操作
if (i == inverseIndex) {
item = next;
next = next.getNext();
//因为后移了一步, 需要确定next不为null, 满足反转条件
if (next == null) {
break;
}
}
i++;
item.setNext(last);
last = item;
item = next;
next = next.getNext();
}
item.setNext(last);
return item;
}
4. 求链表中间节点
/**
* 求链表中间接节点
*
* @return
*/
public static Node middleNode(Node node) {
Node fast = node;
Node slow = node;
while ((fast = fast.getNext()) != null && fast.getNext() != null) {
fast = fast.getNext();
slow = slow.getNext();
}
return slow;
}