24. 两两交换链表中的节点
题目:
分析:
这是我这次离独立写出中等题最近的一次,大体的思路已经写出来了,但是不知道应该怎么返回真正头节点的(以后发现头节点发生改变的一定要记得引入虚拟头节点!)
没实现最终效果但思路已经大致一样的代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode l1,l2;
l1 = head;
l2 = l1.next;
while(l1 != null && l1.next != null){
l1.next = l1.next.next; // 先将l1指向l2的下一个节点
l2.next = l1; // l2指向l1
// 交换完毕
// 更新指针,为下次循环做准备
l1 = l1.next;
l2 = l2.next.next;
}
}
}
我们引入一个虚拟头节点 dummyHead,其 next 节点为 head 节点。定义一个 ListNode 类型的 cur 指向 虚拟节点。由于我们的虚拟节点是在 head 前,所以我们上面的循环条件要多加一个 next 指针。
在我们的循环中,我们定义 L1 为两个节点中的第一个节点(cur.next), L2 为节点中的第二个节点(cur.next.next)。
- 我们向将 L1 的next 指针指向第三个元素,也就是 L2 的下一个元素,即 L1.next = L1.next.next;
- 将 L2 的next 指针指向 L1, L2.next = L1;
- 将 cur.next 指向 L2(在第一次中,由于 cur 和dommyHead实际上是同一个指针,所以此时的head节点就变为了 L2);
- 将 cur 更新为第三个元素。(这样第三步的时候,由于cur已经被赋了新值,所以不再会影响head!)
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
// 由于头节点会改变,所以我们引入虚拟头节点
ListNode dummyNode = new ListNode(0, head);
// 设置一个指针,用于遍历,初始指向虚拟头节点
ListNode current = dummyNode;
// 要怎么修改呢?第一个节点的next指向第三个,第二个节点指向第一个节点,cur指向第二个节点
while(current.next != null && current.next.next != null){
ListNode L1 = current.next; // 两个元素中的第一个元素
ListNode L2 = current.next.next;
L1.next = L2.next;
L2.next = L1;
current.next = L2; // 若是第一次,此时由于cur和dummyNode实际上操作的是同一个节点
// 于是,我们便将dummyNode的next即head变为了L2
// 现在我们需要做的就是改变cur指针,为了终止循环
// 将cur更改为现在两个元素中的第二个元素,即下一对元素的dummyNode。
current = current.next.next;
}
return dummyNode.next;
}
}