0565. 数组嵌套
大约 3 分钟
---
0565. 数组嵌套
- 标签:深度优先搜索、数组
- 难度:中等
题目链接
题目大意
描述:
给定索引从 开始长度为 的数组 ,包含 的所有整数。
要求:
找到最大的集合 并返回其大小,其中 且遵守以下的规则。
假设选择索引为 的元素 为 的第一个元素, 的下一个元素应该是 ,之后是 以此类推,不断添加直到 出现重复的元素。
说明:
- 。
- 。
- 中不含有重复的元素。
示例:
- 示例 1:
输入: A = [5,4,0,3,1,6,2]
输出: 4
解释:
A[0] = 5, A[1] = 4, A[2] = 0, A[3] = 3, A[4] = 1, A[5] = 6, A[6] = 2.
其中一种最长的 S[K]:
S[0] = {A[0], A[5], A[6], A[2]} = {5, 6, 2, 0}解题思路
思路 1:
将数组 看成一个有向图:每个下标 指向唯一的下标 。由于 是 的一个排列(元素不重复,且都在范围内),图中每个节点出度均为 ,因此整张图由若干个「不相交的简单环」组成。题目中的集合 实际上就是从起点 出发顺着边前进直到首次重复时形成的环,答案即为所有环中最大的长度。
做法:从每个未访问的起点 出发,沿着 走,并统计本次路径中第一次遇到已访问节点前的步数,即该环的长度。用布尔数组(或集合) 标记已经访问过的下标,保证每个下标只被遍历一次。
变量含义:
- :数组长度。
- :输入数组。
- :访问标记数组,
visited[x] = True表示下标 已被计入某个环或已遍历过。 - :当前找到的最大环长。
- :从某个起点出发的游标位置。
- :从当前起点出发走到重复前累计的长度。
算法步骤:
- 初始化 全为
False,。 - 枚举起点 。若
visited[i]为True,跳过;否则从 出发:- 置 ,。
- 当
visited[curr]为False时:标记visited[curr] = True,令 ,。 - 本轮结束时,更新 。
- 返回 。
思路 1:代码
class Solution:
def arrayNesting(self, nums: List[int]) -> int:
n = len(nums)
visited = [False] * n # 访问标记:True 表示该下标已被遍历过
ans = 0
for i in range(n):
if visited[i]:
continue # 已处理过,跳过
cnt = 0
curr = i
# 顺着 i -> nums[i] -> nums[nums[i]] ... 直到遇到已访问位置
while not visited[curr]:
visited[curr] = True
curr = nums[curr]
cnt += 1
# 本次从起点 i 出发形成的环长度为 cnt
if cnt > ans:
ans = cnt
return ans思路 1:复杂度分析
- 时间复杂度:。每个下标至多被访问一次。
- 空间复杂度:。使用了大小为 的 辅助数组。