每日总结day04
写在前面:今天感冒还是依旧,我真的服了
24|两两交换链表中的节点
题目
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)
思路
- 使用一个虚拟头结点方便操作
- 用一个指针每次跳两个,并修改指针指向的下两个节点的位置
- 在修改时要使用一个temp指针,防止节点丢失
新思想
- 虚拟头结点统一操作
代码
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null)
return null;
ListNode demmey = new ListNode(0);
demmey.next = head;
ListNode p = demmey;
ListNode q = demmey;
while(!(p.next == null || p.next.next == null)) {
q = p.next.next;
p.next.next = p.next.next.next;
q.next = p.next;
p.next = q;
p = p.next.next;
}
return demmey.next;
}
}
19|删除链表的倒数第N个节点
题目
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
思路
- 使用虚拟头结点
- 使用快慢指针,快指针比慢指针快N个节点
- 当快指针到达最后一个节点时,慢指针到达倒数第N+1个节点
- 删除倒数第N个节点即可
新思想
- 虚拟头结点
- 快慢指针的不同用法
代码
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode demmey = new ListNode(0);
demmey.next = head;
ListNode pre = demmey;
ListNode cur = demmey;
if(head == null || n <= 0)
return null;
while(pre != null && n != 0) {
pre = pre.next;
n--;
}
if(pre == null)
return null;
while(pre.next != null) {
pre = pre.next;
cur = cur.next;
}
cur.next = cur.next.next;
return demmey.next;
}
}
面试题02.07|链表相交
题目
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
注意,函数返回结果后,链表必须 保持其原始结构。
思路
- 设置虚拟头结点
- 设置两个指针分别指向两个链表的起始位置
- 分别遍历两个链表得到二者的长度len_a、len_b
- 长的链表的指针向前移动|len_a-len_b|,因为链表是一直相交到末尾,所以一定是从剩余长度相等的地方开始相交的
- 然后两个指针同时移动,当指针指向同一个节点时结束
新思想
- 对链表特殊结构的特点进行分析
代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int len_a = 0;
int len_b = 0;
ListNode pa = headA;
ListNode pb = headB;
while(pa != null) {
len_a++;
pa = pa.next;
}
while(pb != null) {
len_b++;
pb = pb.next;
}
pa = headA;
pb = headB;
int diff = len_a - len_b;
int i = 0;
if(diff > 0) {
while(--diff >= 0) {
pa = pa.next;
}
} else {
diff = -diff;
while(--diff >= 0) {
pb = pb.next;
}
}
while(pa != pb && pa != null) {
pa = pa.next;
pb = pb.next;
}
if(pa != null)
return pa;
else
return null;
}
}
142|环形链表Π
题目
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
思路
- 设置快慢指针,快指针每次走两格,慢指针每次走一格
- 如果快指针或者快指针的下一个为
null
则没有环 - 如果快慢指针相遇了,说明有环
- 从头结点开始走一个指针,同时从快慢指针相遇的地方走一个指针,两个指针相遇的地方就是循环入口
- (这题新碰到对数学能力要求比较高)
新思想
- 对环形链表的特点进行分析
- 快慢指针的新用法
- (数学功底要好)
代码
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
while(fast == slow) {
ListNode index1 = fast;
ListNode index2 = head;
while(index1 != index2) {
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}