565. 数组嵌套

Difficulty
Medium
Tags
DFS
并查集
URL
https://leetcode.cn/problems/array-nesting/
Star
索引从0开始长度为N的数组A,包含0N - 1的所有整数。找到最大的集合S并返回其大小,其中 S[i] = {A[i], A[A[i]], A[A[A[i]]], ... }且遵守以下的规则。
假设选择索引为i的元素A[i]S的第一个元素,S的下一个元素应该是A[A[i]],之后是A[A[A[i]]]... 以此类推,不断添加直到S出现重复的元素。
示例 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. N[1, 20,000]之间的整数。
  1. A中不含有重复的元素。
  1. A中的元素大小在[0, N-1]之间。
通过次数35,638提交次数57,824

法1 并查集

思路
多写几个S 出来,就会发现本题是找最大的环,然后可以使用 并查集来找
题解
class UnionFind: def __init__(self, n): self.root = [i for i in range(n)] self.size = [1 for _ in range(n)] def find(self, x): if self.root[x] != x: self.root[x] = self.find(self.root[x]) return self.root[x] def union(self, x, y): root_x = self.find(x) root_y = self.find(y) if root_x != root_y: if self.size[root_x] > self.size[root_y]: self.root[root_y] = root_x self.size[root_x] += self.size[root_y] else: self.root[root_x] = root_y self.size[root_y] += self.size[root_x] class Solution: def arrayNesting(self, nums: List[int]) -> int: # 转化为找最大的环 uf = UnionFind(len(nums)) for i in range(len(nums)): uf.union(nums[i], nums[nums[i]]) return max(uf.size)

法2 DFS

思路
按照法1的思路,找最大的环,那么可以使用DFS来找最长的路径
题解
class Solution: def arrayNesting(self, nums: List[int]) -> int: res = 0 self.path=set() for i in range(0, len(nums)): res = max(res, self.dfs(nums=nums, i=i)) return res def dfs(self, nums, i): if i in self.path: return 0 self.path.add(i) res = 1 + self.dfs(nums, nums[i]) return res

法3 技巧:原地负数标记法

思路
遍历每个位置,如果不为负数,开启循环标记; 循环标记过程中,访问的每个位置,标记为相反数,直到遇到负数停止循环,并记录长度;
题解
class Solution: def arrayNesting(self, nums: List[int]) -> int: res = 0 for i in range(0, len(nums)): if nums[i] >= 0: count = 0 idx = i while nums[idx] >= 0: count += 1 temp = nums[idx] nums[idx] = -1 idx = temp res = max(res, count) return res