problem
A zero-indexed array A consisting of N different integers is given.
The array contains all integers in the range [0, N - 1].Sets S[K] for 0 <= K < N are defined as follows:
S[K] = { A[K], A[A[K]], A[A[A[K]]], … }.
Sets S[K] are finite for each K and should NOT contain duplicates.
Write a function that given an array A consisting of N integers,
return the size of the largest set S[K] for this array.
Note:
- N is an integer within the range [1, 20,000].
- The elements of A are all distinct.
- Each element of array A is an integer within the range [0, N-1].
solution
这个问题中所提到的定义很像抽象代数中的循环群,只不过已经很久没学了,具体使用的数学工具已经忘得差不多了,所以在这里只使用了一些编程的技巧来解答这个问题,题中想要找出最长的S[k],我们可以发现S[k]都可以构成一个循环,因此我们可以使用python中的set这个数据结构,来完成这个任务,思路就是使用main_set
来表示所有已遍历过的数字
,使用tmp_set
来保存这次的遍历数字,那么tmp_set
的最大值就是要求的结果,超过了14%的提交。
class Solution(object):
def arrayNesting(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
main_set = set()
tmp_set = set()
ans = 0
for i in range(n):
if not i in main_set:
t = i
m = 0
while not t in tmp_set:
tmp_set.add(t)
t = nums[t]
m += 1
main_set = main_set | tmp_set
print(m)
ans = max(ans, m)
else:
continue
return ans
在写这篇博客的时候感觉可以只需要一个set就可以,经过优化以后超过了89%的提交。
class Solution(object):
def arrayNesting(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
main_set = set()
ans = 0
for i in range(n):
if nums[i] not in main_set:
tmp = 0
t = nums[i]
while t not in main_set:
main_set.add(t)
tmp += 1
t = nums[t]
ans = max(ans, tmp)
else:
continue
return ans
在上面的代码中使用set作为标记是否遍历过的数据结构,实际上对于这个任务完全可以使用visited=list()来标记,只不过实际上set的时间复杂度也是O(1)所以就不在这方面进行优化了(这里就是使用数据结构代替想法)。
上面的这个想法就是新建一个与原数组相同长度的标记数组来标记已遍历元素,而实际上在这个问题中元素遍历过一次之后就没用了,因此可以不使用额外的空间来解决这个问题,也就是说遍历之后就把数字设置为原来不存在的数字作为标记(N is an integer within the range [1, 20,000].),这个想法时间上提升应该不大,因为只是标记方式改变了,但是空间上将原来的 O(n) 降为了 O(1) 。