目录
Leetcode 24 两两交换链表中的节点
文档讲解:代码随想录_两两交换链表中的节点
视频讲解:b站讲解
第一想法:两个两个为一组,然后使用两个临时指针cur和pre,再用另外一个临时指针记录cur的后一个节点,然后改变cur和pre下一个节点的指向,然后再移动cur和pre的位置,但总是出错,另外奇数个节点和偶数个节点要分开考虑吗?
学习记录:
设计一个虚拟头节点,一开始cur指向这个虚拟头节点,要交换的内容不是cur,交换的是cur后两个节点的指向。不着急移动cur的位置,先把链表前后的连接顺序理清楚之后,再将cur移动到下次的位置上。
移动完成之后链表的位置,cur依旧指向下次要交换的两个节点的前一个节点,因此是移动到交换后节点1的位置上。
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null || head.next==null){
return head;
}
ListNode dummp = new ListNode(-1,head);
ListNode cur = dummp;
head = head.next;
while(cur.next!=null && cur.next.next !=null){
ListNode fir = cur.next;
ListNode sec = cur.next.next;
ListNode thi = cur.next.next.next;
cur.next = sec;
sec.next = fir;
fir.next = thi;
cur = fir;
}
return head;
}
}
Leetcode 19 删除链表的倒数第N个节点
文档讲解:代码随想录_删除链表的倒数第N个节点
视频讲解:b站讲解
第一想法:这道题终于是不看解析写出来了
首先遍历整个链表到结尾,得到整个链表的长度,然后通过循环找到要删除节点的前一个节点,然后执行删除该节点的操作。此处依旧利用了虚拟头节点帮助解题。
// 我的第一想法的代码
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
int len = 0;
ListNode dummp = new ListNode(-1,head);
ListNode cur = dummp;
while(cur.next!=null){
len = len+1;
cur = cur.next;
}
cur = dummp;
for(int i=0;i<len-n;i++){
cur = cur.next;
}
cur.next = cur.next.next;
return dummp.next;
}
}
学习记录:
妙啊,可以使用一次循环遍历求解,利用两个临时指针,通过合理设置两个临时指针之间的间隔,是快指针指到链表结尾的时候慢指针刚好指到要删除节点的前一个位置。
快慢指针之间的间隔为n+1,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图(节点3为要删除的节点):
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
int len = 0;
ListNode dummp = new ListNode(-1,head);
ListNode fast = dummp;
ListNode slow = dummp;
for(int i=0;i<n+1;i++){
fast = fast.next;
}
while(fast!=null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummp.next;
}
}
面试题 02.07 链表相交
文档讲解:代码随想录_链表相交
第一想法:双重循环?没什么具体的想法
学习记录:
要注意链表与数组的缺点,此处的相同不是数值相同,而是指针相等。
举例:
- 看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点
- 我们求出两个链表的长度(循环遍历),并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:
-
此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。否则循环退出返回空指针。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0;
int lenB = 0;
while(curA!=null){
lenA++;
curA=curA.next;
}
while(curB!=null){
lenB++;
curB=curB.next;
}
curA = headA;
curB = headB;
if(lenB > lenA){
ListNode temp = curA;
curA = curB;
curB = temp;
int templ=lenA;
lenA = lenB;
lenB = templ;
}
int dif = lenA-lenB;
for(int i = 0;i<dif;i++){
curA = curA.next;
}
while(curA!=null){
if(curA==curB){
return curA;
}
curA=curA.next;
curB=curB.next;
}
return null;
}
}
Leetcode 142 环形链表
题目链接:Leetcode_142_环形链表
文档讲解:代码随想录_环形链表
视频讲解:b站讲解
第一想法:没什么想法,不知道怎么找啊
学习记录:
该问题可以分解为两个问题:(1)判断有没有环;(2)找环的入口
- 判断有没有环:可以设置双指针,一个快指针(一次走两个节点),一个慢指针(一次走一个节点),如果存在环,快慢指针终会相遇(相当于追及问题,进入环之后,快指针以每次1个节点的速度靠近慢指针,所以终会相遇)
- 找环的入口:一个指针从相遇点开始走,另外一个指针从头节点开始走,相遇的时候一定是在环型的入口处,推导可以见代码随想录。(太妙了!)
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;
if(fast==slow){
ListNode index1 = fast;
ListNode index2 = head;
while(index1!=index2){
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}