代码随想录算法训练营第四天| 22. 两两交换链表中的节点、 19.删除链表的倒数第N个节点、面试题 02.07. 链表相交
24. 两两交换链表中的节点
题目描述
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
算法实现(哑节点)
待反转的链表
| 1 | 2 | 3 | 4 | 5 |
|---|
添加哑节点
| 0 | 1 | 2 | 3 | 4 | 5 |
|---|
反转链表
| prev | head | head.next | head.next.next | ||
|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 |
- 暂时保存head.next.next 节点为temp 以为下面旋转的时候该结点没有指向 就会无法找到
- prev.next节点指向head.next
- head.next .next指向 head
- head.next指向temp节点
反转后的链表
| prev | 2 | 1 | 3 | 4 | 5 |
|---|
- 开始移动prev节点的指向 head节点(1)
- 移动head 指针到下一个节点 head=head.next
public static ListNode swapPairs(ListNode head) {
ListNode dummyNode = new ListNode(-1);
dummyNode.next = head;
ListNode prev = dummyNode;
while (prev.next != null && prev.next.next != null) {
ListNode temp = head.next.next; //save the node
prev.next = head.next;
head.next.next = head;
head.next = temp;
prev = head; //move the pre node
head = head.next; //move the next node
}
return dummyNode.next;
}
19. 删除链表的倒数第 N 个结点
题目描述
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
算法实现
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyNode = new ListNode(-1); //添加 dummyNode
dummyNode.next=head;
ListNode fast=dummyNode;
ListNode slow=dummyNode;
while (n-->=0){// fast 先移动n+1 步
fast=fast.next;
}
while(fast!=null){// 同时移动
fast=fast.next;
slow=slow.next;
}
// slow 节点是要删除的节点的前一个节点
slow.next=slow.next.next;
return dummyNode.next;
}
面试题 02.07. 链表相交
题目描述
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
算法实现
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (null == headA || null == headB) {
return null;
}
ListNode pA = headA;
ListNode pB = headB;
while (pA != pB) {
pA = pA == null ? headB : pA.next;
pB = pB == null ? headA : pB.next;
}
return pA;
}
142. 环形链表 II
题目描述
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
算法实现
集合Set实现
public ListNode detectCycle(ListNode head) {
Set<ListNode> set = new HashSet<>();
while (head != null) {
if (!set.add(head)) { // 代表set集合中已经有该节点
return head;
}
head = head.next;
}
return null;
}
快慢指针
public ListNode detectCycle1(ListNode head) {
if (head == null) return null;
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {// 存在环
ListNode newFastNode = fast;
ListNode newSlowNode = head;
while (newFastNode != newSlowNode) {
newFastNode = newFastNode.next;
newSlowNode = newSlowNode.next;
}
return newFastNode;
}
}
return null;
}