
解题思路:
- 引入哑节点: 简化头节点删除操作,统一处理所有边界条件。
- 快慢指针法: 快指针先移动 n 步,确保快慢指针距离为 n,之后同步移动快慢指针。当快指针到达末尾时,慢指针指向倒数第 n 个节点的前驱。
- 删除节点: 调整慢指针的 next 指针,跳过目标节点。
Java代码:
class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummy = new ListNode(-1);dummy.next = head;ListNode fast = dummy, slow = dummy;for (int i = 0; i < n; i++) fast = fast.next;while (fast.next != null) {slow = slow.next;fast = fast.next;}slow.next = slow.next.next;return dummy.next;}
}
复杂度分析:
- 时间复杂度: O(m),其中m是链表的长度。
- 空间复杂度: O(1),只使用了常数级别的额外空间。

解题思路:
- 创建哑节点: 作为新链表的头前驱,统一处理头节点交换。
- 初始化指针: prevEnd:标记当前交换对的末尾,初始指向哑节点。first 和 second:指向待交换的两个节点。
- 交换节点: 保存 second 的下一个节点 nextNode。调整指针顺序:prevEnd → second → first → nextNode。
- 移动指针: prevEnd 移动到当前交换后的第一个节点(原 first),继续处理下一对。
- 终止条件: 当剩余节点不足两个时停止循环。
Java代码:
class Solution {public ListNode swapPairs(ListNode head) {if (head == null || head.next == null) return head;ListNode dummy = new ListNode(-1);dummy.next = head;ListNode prevEnd = dummy;ListNode first = prevEnd.next;ListNode second = first.next;while (first != null && second != null) {ListNode nextNode = second.next;prevEnd.next = second;second.next = first;first.next = nextNode;prevEnd = first;first = prevEnd.next;if (first == null) break;second = first.next;if (second == null) break;}return dummy.next;}
}
复杂度分析:
- 时间复杂度: O(n),遍历链表一次,每个节点操作为常数时间。
- 空间复杂度: O(1),仅使用哑节点和指针变量,常数空间。