代码随想录day4
两两交换链表中的节点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
思路
模拟链表交换节点操作
递归实现
class Solution {
// 递归实现
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null)
return head;
ListNode next = head.next;
ListNode nextNode = swapPairs(next.next);
next.next = head;
head.next = nextNode;
return next;
}
}
借助于虚拟头结点模拟三步交换操作
class Solution {
// 模拟交换实现
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode cur = dummy;
while(cur.next != null && cur.next.next != null){
// 保存中间变量
ListNode tmp = cur.next.next.next;
ListNode first = cur.next;
ListNode second = cur.next.next;
// 三步操作
cur.next = second;
second.next = first;
first.next = tmp;
cur = first;
}
return dummy.next;
}
}
删除链表的倒数第N个节点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
思路
先得出链表长度,再去寻找需要删除的节点 – 遍历查找
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode cur = head;
int size = 0;
while(cur != null){
size++;
cur = cur.next;
}
// 是否删除头结点
if(size == n)
return head.next;
cur = head;
// 找到前一个节点
for(int i = 0;i < size - n - 1;i++){
cur = cur.next;
}
ListNode nextnext = cur.next.next;
cur.next = nextnext;
return head;
}
}
双指针思想:双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。
class Solution {
// 双指针
public ListNode removeNthFromEnd(ListNode head, int n) {
// 借助虚拟头节点
ListNode dummy = new ListNode(-1,head);
ListNode slow = dummy,fast = dummy;
// 让快指针先走N+1步,这样让slow节点位于需要删除节点的前一个
for(int i = 0;i < n + 1;i++){
fast = fast.next;
}
// 找到需要删除的前一个节点
while(fast != null){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
注意:删除第N个节点,那么我们当前遍历的指针一定要指向 第N个节点的前一个节点
环形链表 II
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
思路
快慢指针思想:先判断是否有环。
若有环,经过数学追击思维分析,可知:
双指针第二次相遇:
令 fast 重新指向链表头部节点。此时 f=0,s=nb。
slow 和 fast 同时每轮向前走 111 步。
当 fast 指针走到 f=a步时,slow 指针走到 s=a+nb 步。此时两指针重合,并同时指向链表环入口,返回 slow 指向的节点即可。
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head,fast =head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
// 第一次相遇
if(slow == fast){
fast = head;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
return fast;
}
}
return null;
}
}