目录
两两交换链表中的节点
题目链接:24. 两两交换链表中的节点
---给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
思路:首先需要定义一个虚拟指针dummy,方便后续输出头节点;
然后定义一个cur指针:指向要进行交换操作的两个结点的前面一个结点;
之后对其进行以下三步操作即可
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(-1,head);
ListNode cur = dummy;
//定义三个临时节点,方便后续交换操作
ListNode node1,node2,node3;
//当下一轮进行交换的结点不足两个时,跳出循环,直接输出就行了
while(cur.next != null && cur.next.next != null){
node1 = cur.next;
node2 = cur.next.next;
node3 = node2.next;
//两两交换操作
cur.next = node2;
node2.next = node1;
node1.next = node3;
//更新cur指针
cur = node1;
}
return dummy.next;
}
}
删除链表的倒数第N个结点
题目链接:19. 删除链表的倒数第 N 个结点
---给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
思路:用到快慢指针,同时因为头结点也有可能被删除,需要定义虚拟指针方便输出最后结果。
slow指针:获指向被删节点的前一个节点
fast指针:用于遍历链表,直至fast.next为空
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1,head);
ListNode slow = dummy,fast = dummy;
while(n-- > 0){
fast = fast.next;
}
//题中n的值小于等于结点数量,所以fast不可能是空节点
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
//此时slow节点就是被删节点的前一个节点,slow.next结点不可能在fast后边,所以slow.next也不可能是空节点
slow.next = slow.next.next;
return dummy.next;
}
}
链表相交
题目链接:链表相交
---给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
思路:采用合并链表的思想,定义p1,p2两指针
p1:遍历headA,为空时则遍历headB,实现"合并链表"
p2:遍历headB,为空时则遍历headA,实现"合并链表"
退出循环后,p1、p2遍历过的结点为:
p1:a1、a2、c1、c2、c3、b1、b2、b3、c1
p2:b1、b2、b3、c1、c2、c3、a1、a2、c1
p1和p2两者必定相遇在第二个“c1”,实现"链表合并"
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//合并链表,实现同步移动
ListNode p1 = headA,p2 = headB;
while(p1 != p2){
//p1 走一步,如果走到 A 链表末尾,转到 B 链表
if(p1 == null)p1 = headB;
else p1 = p1.next;
// p2 走一步,如果走到 B 链表末尾,转到 A 链表
if(p2 == null)p2 = headA;
else p2 = p2.next;
}
//如果继续遍历原链表,就相当于追及问题了,也能ac,但耗时太长!!
return p1;
}
}
环形链表||
题目链接:142. 环形链表 II
---给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
思路:用到快慢指针,在两者相交之前,fast指针一次两步,slow指针一次一步。
待相遇之时,快指针所走路程是满指针所走路程的两倍
满足:x + quan1*(z+y) + y= 2*x + 2*quan2*(z+y) + 2 * y, 化简得z = x + (2*quan2-quan1+1)*(z+y)
需要注意:max(2*quan2-quan1) = 0, 此时头结点就是相交点,x = 0,y = 0;
当2*quan2-quan1为负数时,z <= x, 此时 路程x 是 路程z + 圈数的路程(可以为0) ;
所以之后fast从相遇点出发,slow从head出发时,slow是不可能进入环内的,slow与fast一旦相等,那就是链表开始入环的第一个节点!!
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head == null)return null;
ListNode fast = head,slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow)break;
}
//没有环,直接返回null
if(fast.next == null || fast.next.next == null)return null;
//此时fast与slow相交,slow从head出发,fast从相交点出发
slow = head;
while(slow != fast){
slow = slow.next;
fast = fast.next;
}
return fast;
}
}