24.两两交换链表中的节点
视频链接:帮你把链表细节学清楚! | LeetCode:24. 两两交换链表中的节点
思路分析
- 首先考虑,题中说明两个节点的交换,但还需要考虑两个节点之前和之后的节点,所以每次交换涉及到四个节点,建立虚拟节点dummy,指向头节点
- 设置临时变量,cur=dummy,firstNode为要交换的第一个节点,secondNode为要交换的第二个节点,temp为要交换的两个节点的下一个节点
- 开始遍历,同时保证要交换的两个节点都不为空,即cur.next !=null && cur.next.next !=null;若其中一个节点为空,则直接返回头节点即dummy.next
- 开始遍历,先确定好各个变量的位置
- 按照图一中顺序1.2.3,进行操作
- 得到图二中的结果,赋值cur=firstNode,往下遍历
代码如下:
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(0, head);//设置虚拟节点
ListNode cur = dummy;
ListNode temp;//临时节点,保存两个要交还的节点的后一个节点
ListNode firstNode;//临时节点,保存第一个节点
ListNode secondNode;//临时节点,保存第二个节点
//要交换两个节点,cur为虚拟节点,即要交换的节点之前的节点,要保证要交换的两个节点不为空
while (cur.next != null && cur.next.next != null) {
firstNode = cur.next;
secondNode = cur.next.next;
temp = cur.next.next.next;
cur.next = secondNode;//步骤一
firstNode.next = temp;//步骤二
secondNode.next = firstNode;//步骤三
cur = firstNode;
}
return dummy.next;
}
总结
我在一开始没有确定好cur的位置,初始把cur定为虚拟节点的下一个节点的位置。开始遍历时,while循环控制 cur.next !=null 不能保证,转换一次后两个节点都不为空、cur.next !=null && cur.next.next !下一次转换即将开始前,进行变量赋值,会在判断即将要交换的两个节点的下一个节点为空,无法交换。所以确定每次的目标cur的位置很重要,其他变量都是在他的基础上运用.next
19.删除链表的倒数第N个节点
视频链接:链表遍历学清楚! | LeetCode:19.删除链表倒数第N个节点
思路分析
- 首先创建虚拟头节点,方便处理头节点操作
- 定义fast指针和slow指针,初始位置为虚拟头节点,如图
- fast先走n步,fast和slow首先有n个差距,在同时向前遍历,当fast到达最后一个非空节点时,slow刚好到达要删除的倒数第n个节点的前一个节点,如图
- 删除节点
代码如下:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
ListNode fast = dummy;
ListNode slow = dummy;
for (int i = 0; i < n; i++) {
fast = fast.next;
}
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
总结
我一开始想用暴力,直接for循环i--,不至于双指针吧,转念一想,这不链表吗,上哪知道长度去,双指针不无道理
面试题 02.07. 链表相交
视频链接:链表遍历学清楚! | LeetCode:19.删除链表倒数第N个节点
思路分析
转载这个大神的解题,思路我认为是加法交换律a+b=b+a,但是不容易想到 ,太妙了
代码如下:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode A = headA, B = headB;
while (A != B) {
A = A != null ? A.next : headB;
B = B != null ? B.next : headA;
}
return A;
}
}