文章目录
- 需求
- 代码
- 代码解释
- 结尾
需求
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
示例 3:
输入:head = [1]
输出:[1]
提示:
链表中节点的数目在范围 [0, 100] 内
0 <= Node.val <= 100
代码
public ListNode swapPairs(ListNode head) {
if( head == null || head.next == null ){
return head;
}
ListNode preHead = new ListNode(-1, head);
ListNode cur = preHead;
while( cur.next != null && cur.next.next != null ){
// 拿出前三个元素
ListNode node1 = cur.next;
ListNode node2 = node1.next;
ListNode node3 = node2.next;
// 交换
node1.next = node3;
node2.next = node1;
cur.next = node2;
// 重置 cur
cur = node1;
}
return preHead.next;
}
代码解释
处理特殊情况:
如果链表为空或者只有一个节点,直接返回 head。因为在这种情况下没有必要进行交换。
if (head == null || head.next == null) {
return head;
}
初始化虚拟头节点:
ListNode preHead = new ListNode(-1, head);
创建一个虚拟头节点 preHead,它的 next 指向链表的实际头节点 head。这样做可以简化处理链表头部的交换操作。
初始化 cur 指针:
ListNode cur = preHead;
cur 指针用来跟踪当前处理的位置,最初指向 preHead。在交换过程中,cur 负责保持对链表已经交换部分的连接。
交换节点:
while (cur.next != null && cur.next.next != null) {
// 拿出前三个元素
ListNode node1 = cur.next;
ListNode node2 = node1.next;
ListNode node3 = node2.next;
// 交换
node1.next = node3;
node2.next = node1;
cur.next = node2;
// 重置 cur
cur = node1;
}
提取三个节点:
node1:当前 cur 节点的下一个节点。
node2:node1 的下一个节点。
node3:node2 的下一个节点。
交换节点:
node1.next = node3:将 node1 的 next 指向 node3(即交换后 node1 之后的节点)。
node2.next = node1:将 node2 的 next 指向 node1(交换节点 2 和节点 1)。
cur.next = node2:将 cur.next 更新为 node2,完成交换后的连接。
更新 cur:
cur = node1:将 cur 指向 node1,为下一对节点的交换做好准备。
返回结果:
return preHead.next;
返回 preHead.next,它指向链表交换后的新头节点。
执行结果:
结尾
以上 是我对这道算法的一些遐想和延伸, 可能不是最优解, 但是算法的优化嘛 本身就是一个思索的过程, 能在这个思索和迭代的过程中有所收获和乐趣就是在成长了, 欢迎大家一起来交流更多的解答…