24.两两交换链表中的节点
题目链接/文章讲解/视频讲解: https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html
思路:首先我们要交换两个节点的位置,我们就得知道节点1(如下图)的前一个节点,所以我们首先得先创建一个虚拟节点cur,然后开始交换节点的逻辑
- 将cur.next指向节点2,当cur的next指向节点2后,节点1就会被断开,所以我们要提前创建temp来存储节点1
- 将节点2指向temp,因为此时节点1已经被断开无法找到这个节点,当节点2指向temp时,节点3也会被断开,所以也要提前创建temp1存储节点3
- 最后将节点1指向temp,此时这个链表的前两个元素就交换完成了
public ListNode swapPairs(ListNode head) {
// 要交换节点,我们就得知道节点的上一个节点
// 所以我们需要定义一个虚拟节点
ListNode dummyhead = new ListNode(-1,head);
// 用来遍历和交换节点
ListNode cur = dummyhead;
ListNode temp,temp1;
// 偶数和奇数情况的终止条件
while(cur.next!=null && cur.next.next!=null){
// 开始交换节点
// 1、将cur.next指向节点2,当我们修改后,节点1就没有被指向(被断开),所以我们要提前存储节点1
temp = cur.next; // 存储节点1
// 2、将节点2的next指向节点1,同时节点3就会断开,所以我们还得再提前存储节点3
// 存储节点3
temp1 = cur.next.next.next; // 循环条件中,我们已经判断前两个节点不会为空,所以这里不会出现空指针异常,最多就是temp1=null
// 3、将节点1的next指向节点3
// 交换逻辑
cur.next = cur.next.next; // 步骤1
cur.next.next = temp; // 步骤2
temp.next = temp1; // 步骤3
// 移动cur
cur = cur.next.next;
}
return dummyhead.next;
}
19.删除链表中的倒数第N个节点
思路:要删除链表中倒数第N个节点,我们就得知道倒数第N+1个节点得位置,这我们才能删除掉倒数第N个节点,思路就是利用双指针法定义快慢指针,首先将快指针前进N+1个,然后快慢指针同时移动,直到快指针指向null就停止,这样慢指针就停留在N+1的这个节点上
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode s = new ListNode(-1,head);
ListNode p1 = s; // 慢指针
ListNode p2 = s; // 快指针
// 快指针先前进n+1
for(int i=0; i<n+1; i++){
p2 = p2.next;
}
// 再同时移动快慢指针,让慢指针停留在倒数第n个节点的前一个节点
while(p2!=null){
p1=p1.next;
p2=p2.next;
}
// 执行删除操作
p1.next = p1.next.next;
return s.next;
}
// 执行删除操作
p1.next = p1.next.next;
return s.next;
}