LeetCode 剑指 Offer II 链表 专题总结

在这里插入图片描述

输入:head = [3,2,0,-4], pos = 1

输出:返回索引为 1 的链表节点

解释:链表中有一个环,其尾部连接到第二个节点。

思路:

方法一:哈希表

可以通过哈希表记录,如果遇到哈希表里面有的就相当于第一个入环口

方法二:快慢指针

a为环外长度,b为入环口到相遇的长度,c为相遇到入环口长度

a + n * (b + c) + b = 2 * (a + b)第一次相遇的路程

得 a = (n - 1) * (b + c) + b;

所以 fast 一次一步再走 a 必然会遇到 slow

//快慢指针

class Solution {

public:

ListNode *detectCycle(ListNode *head) {

ListNode *fast = head;

ListNode *slow = head;

while(1) {//第一次相遇

//遇到空指针相当于不是循环,return

if(fast == nullptr || fast->next == nullptr)

return nullptr;

slow = slow->next;

fast = fast->next->next;

if(slow == fast) break;

}

fast = head;

while(fast != slow) {

fast = fast->next;

slow = slow->next;

}

return slow;

}

};

023. 两个链表的第一个重合节点

=================================================================================

题目:

给定两个单链表的头节点 headA 和 headB ,请找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交:

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

示例:

在这里插入图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3

输出:Intersected at ‘8’

解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。

从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。

在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

思路:

方法一:哈希表

把a加入哈希表,遍历b判断是否有节点在哈希表中,有则返回,无则不相交

方法二:双指针

a = a + b, b = b + a

如果a和b相交的话,在遍历对方那部分的时候就可以找到相交的节点

//双指针

class Solution {

public:

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {

if(headA == nullptr || headB == nullptr) return nullptr;

ListNode *curA = headA;

ListNode *curB = headB;

while(curA != curB) {

curA = curA == nullptr? headB : curA->next;

curB = curB == nullptr? headA : curB->next;

}

return curA;

}

};

024. 反转链表

=========================================================================

题目:

给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点。

示例:

在这里插入图片描述

输入:head = [1,2,3,4,5]

输出:[5,4,3,2,1]

思路:

创建两个双指针,从头结点和首节点开始一直反转

class Solution {

public:

ListNode* reverseList(ListNode* head) {

ListNode *pre = nullptr;

ListNode *cur = head;

while(cur != nullptr) {

ListNode* next = cur->next;

cur->next = pre;

pre = cur;

cur = next;

}

return pre;

}

};

025. 链表中的两数相加

=============================================================================

题目:

给定两个 非空链表 l1和 l2 来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相> 加会返回一个新的链表。

可以假设除了数字 0 之外,这两个数字都不会以零开头。

示例:

在这里插入图片描述

输入:l1 = [7,2,4,3], l2 = [5,6,4]

输出:[7,8,0,7]

思路:

方法一:用两个栈(麻烦)

先用两个栈进行反转,相加,但最后还要反转链表

方法二:翻转链表

翻转链表后相加,再翻转

class Solution {

public:

ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {

l1 = reverseList(l1);

l2 = reverseList(l2);

return reverseList(addList(l1, l2));

}

//链表相加

ListNode* addList(ListNode* l1, ListNode* l2) {

int ans = 0;

ListNode *node = new ListNode(-1);

ListNode *dummy = node;

while(l1 || l2) {

int x = 0, y = 0;

if(l1) {

x = l1->val;

l1 = l1->next;

}

if(l2) {

y = l2->val;

l2 = l2->next;

}

int num = (x + y + ans) % 10;

ans = (x + y + ans) / 10;

node->next = new ListNode(num);

node = node->next;

}

if(ans) {//进位的话再加上

node->next = new ListNode(ans);

node = node->next;

}

return dummy->next;

}

//翻转链表

ListNode* reverseList(ListNode* head) {

ListNode *pre = nullptr;

ListNode *cur = head;

while(cur) {

ListNode *next = cur->next;

cur->next = pre;

pre = cur;

cur = next;

}

return pre;

}

};

026. 重排链表

=========================================================================

题目:

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

L0 → L1 → … → Ln-1 → Ln

请将其重新排列后变为:

L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …

不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例:

在这里插入图片描述

输入: head = [1,2,3,4]

输出: [1,4,2,3]

思路:

方法一:线性表

用线性表存储,然后用下表访问线性表,创建新链表

方法二:寻找链表中点 + 链表逆序 + 合并链表

//方法二

class Solution {

public:

void reorderList(ListNode* head) {

//快慢指针找中点

ListNode *fast = head;

ListNode *slow = head;//中点

while(fast != nullptr && fast->next != nullptr) {

fast = fast->next->next;

slow = slow->next;

}

// 翻转后半部分

fast = nullptr;

while(slow != nullptr) {

ListNode *next = slow->next;

slow->next = fast;

fast = slow;

slow = next;

}

slow = head;

//slow为前半部分链表,fast为后半部分链表

while(slow || fast) {

if(slow) {

ListNode *next1 = slow->next;

slow->next = fast;

slow = next1;

}

if(fast) {

ListNode *next2 = fast->next;

fast->next = slow;

fast = next2;

}

}

}

};

027. 回文链表

=========================================================================

题目:

给定一个链表的 头节点 head ,请判断其是否为回文链表。

如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。

示例:

在这里插入图片描述

输入: head = [1,2,3,3,2,1]

输出: true

思路:

  • 寻找中点

  • 翻转后半部分链表

  • 判断前后部分是否回文

class Solution {

public:

bool isPalindrome(ListNode* head) {

//寻找中点

ListNode *fast = head;

ListNode *slow = head;

while(fast != nullptr && fast->next != nullptr) {

fast = fast->next->next;

slow = slow->next;

}

//翻转后半部分

fast = reverseList(slow);

slow = head;//前半部分

//判断是否回文

bool ok = true;

//fast <= slow, 所以while要用fast,下面证明:

//例如:[1,2,1] 此时 slow = 1 -> 2, fast = 1 -> 2,因为2翻转的时候前面的1还指向2

//[1,2,2,1] 此时slow = 1 -> 2 -> 2, fast = 1 -> 2

while(ok && fast != nullptr) {

if(slow->val != fast->val) {

ok = false;

break;

}

fast = fast->next;

slow = slow->next;

}

return ok;

}

//翻转链表

ListNode* reverseList(ListNode* head) {

ListNode *pre = nullptr;

ListNode *cur = head;

while(cur) {

ListNode *next = cur->next;

cur->next = pre;

pre = cur;

cur = next;

}

return pre;

}

};

028. 展平多级双向链表

=============================================================================

题目:

多级双向链表中,除了指向下一个节点和前一个节点指针之外,它还有一个子链表指针,可能指向单独的双向链表。这些子列表>也可能会有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。

给定位于列表第一级的头节点,请扁平化列表,即将这样的多级双向链表展平成普通的双向链表,使所有结点出现在单级双链表中。

示例:

输入:head = [1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12]

输出:[1,2,3,7,8,11,12,9,10,4,5,6]

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

Java架构进阶面试及知识点文档笔记

这份文档共498页,其中包括Java集合,并发编程,JVM,Dubbo,Redis,Spring全家桶,MySQL,Kafka等面试解析及知识点整理

image

Java分布式高级面试问题解析文档

其中都是包括分布式的面试问题解析,内容有分布式消息队列,Redis缓存,分库分表,微服务架构,分布式高可用,读写分离等等!

image

互联网Java程序员面试必备问题解析及文档学习笔记

image

Java架构进阶视频解析合集
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
讲义、实战项目、讲解视频,并且会持续更新!**

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

Java架构进阶面试及知识点文档笔记

这份文档共498页,其中包括Java集合,并发编程,JVM,Dubbo,Redis,Spring全家桶,MySQL,Kafka等面试解析及知识点整理

[外链图片转存中…(img-g0QKczkY-1713462515351)]

Java分布式高级面试问题解析文档

其中都是包括分布式的面试问题解析,内容有分布式消息队列,Redis缓存,分库分表,微服务架构,分布式高可用,读写分离等等!

[外链图片转存中…(img-1smLci7x-1713462515353)]

互联网Java程序员面试必备问题解析及文档学习笔记

[外链图片转存中…(img-mtz4tL9c-1713462515355)]

Java架构进阶视频解析合集
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值