⭐️ 本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 和 [BaguTree Pro] 知识星球提问。
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭将基于 Java / Kotlin 语言,为你分享常见的数据结构与算法问题,及其解题框架思路。
本文是数据结构与算法系列的第 2 篇文章,完整文章目录请移步到文章末尾~
前言
- 链表相交 & 成环问题可以归为一类问题,在面试中出现频率较高;
- 在这篇文章里,我将梳理链表相交 & 成环问题的解法。如果能帮上忙,请务必点赞加关注,这真的对我非常重要。
相关问题 | 提示 & 题解 |
---|---|
160. 相交链表 Intersection of Two Linked Lists | 【题解】 |
141. 环形链表 Linked List Cycle | 【题解】 |
142. 环形链表 II Linked List Cycle II | 【题解】 |
61. 旋转链表 Rotate List | 【题解】 |
(扩展)457. 环形循环数组 Circular Array Loop | 【题解】 |
目录
- 判断链表相交
160. Intersection of Two Linked Lists 相交链表 【题解】
编写一个程序,找到两个单链表相交的起始节点。
解法1:哈希表
1 | kotlin复制代码class Solution { |
复杂度分析:
- 时间复杂度:两个链表的节点最多访问一次,时间复杂度为O(m+n)O(m+n)O(m+n)
- 空间复杂度:以其中一个链表构建哈希表,空间复杂度为O(m)O(m)O(m)
解法2:链表成环
1 | kotlin复制代码class Solution { |
复杂度分析:
- 时间复杂度:两个链表的节点最多访问一次,时间复杂度为O(m+n)O(m+n)O(m+n)
- 空间复杂度:只是用了常量级别变量,空间复杂度为O(1)O(1)O(1)
- 判断链表成环
141. Linked List Cycle 环形链表 【题解】
给定一个链表,判断链表中是否有环。
解法1:哈希表
1 | kotlin复制代码class Solution { |
复杂度分析:
- 时间复杂度:链表的节点最多访问一次,时间复杂度为O(n)O(n)O(n)
- 空间复杂度:哈希表空间复杂度为O(n)O(n)O(n)
解法2:Floyd 判圈算法
1 | kotlin复制代码class Solution { |
复杂度分析:
- 时间复杂度:O(n)O(n)O(n)
- 空间复杂度:只是用了常量级别变量,空间复杂度为O(1)O(1)O(1)
- 判断链表成环起点
142. Linked List Cycle II 环形链表 II 【题解】
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。不允许修改给定的链表。
解法1:哈希表
与 第二节类似,略
解法2:Floyd 判圈算法
1 | kotlin复制代码class Solution { |
复杂度分析:
- 时间复杂度:O(n)O(n)O(n)
- 空间复杂度:只是用了常量级别变量,空间复杂度为O(1)O(1)O(1)
- 旋转链表
给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
解法1:链表成环
先将链表闭合成环,再找到新表头,断开前驱节点的连接。需要注意 k 大于链表长度的情况
1 | kotlin复制代码class Solution { |
复杂度分析:
- 时间复杂度:扫描两趟,时间复杂度为 O(n)O(n)O(n)
- 空间复杂度:使用了常量级别变量,空间复杂度为 O(1)O(1)O(1)
- (扩展) 判断环形循环数组
457. Circular Array Loop 环形循环数组 【题解】
给定一个含有正整数和负整数的环形数组 nums。 如果某个索引中的数 k 为正数,则向前移动 k 个索引。相反,如果是负数 (-k),则向后移动 k 个索引。因为数组是环形的,所以可以假设最后一个元素的下一个元素是第一个元素,而第一个元素的前一个元素是最后一个元素。
确定 nums 中是否存在循环(或周期)。循环必须在相同的索引处开始和结束并且循环长度 > 1。此外,一个循环中的所有运动都必须沿着同一方向进行。换句话说,一个循环中不能同时包括向前的运动和向后的运动。
解法1:哈希表 + 记忆化
1 | kotlin复制代码class Solution { |
复杂度分析:
- 时间复杂度:每个位置最多访问一次,时间复杂度为O(n)O(n)O(n)
- 空间复杂度:哈希表为O(n),O(n),O(n),路径标志为O(n)O(n)O(n),总体为O(n)O(n)O(n)
解法2:快慢指针
1 | kotlin复制代码class Solution { |
推荐阅读
数据结构与算法系列完整目录如下(2023/07/11 更新):
- #1 链表问题总结
- #2 链表相交 & 成环问题总结
- #3 计算器与逆波兰表达式总结
- #4 高楼丢鸡蛋问题总结
- #5 为什么你学不会递归?谈谈我的经验
- #6 回溯算法解题框架总结
- #7 下次面试遇到二分查找,别再写错了
- #8 什么是二叉树?
- #9 什么是二叉堆 & Top K 问题
- #10 使用前缀和数组解决 “区间和查询” 问题
- #11 面试遇到线段树,已经这么卷了吗?
- #12 使用单调队列解决 “滑动窗口最大值” 问题
- #13 使用单调栈解决 “下一个更大元素” 问题
- #14 使用并查集解决 “朋友圈” 问题
- #15 如何实现一个优秀的 HashTable 散列表
- #16 简答一波 HashMap 常见面试题
- #17 二叉树高频题型汇总
- #18 下跳棋,极富想象力的同向双指针模拟
Java & Android 集合框架系列文章: 跳转阅读
LeetCode 上分之旅系列文章:跳转阅读
⭐️ 永远相信美好的事情即将发生,欢迎加入小彭的 Android 交流社群~
本文转载自: 掘金