Array Nesting#
Problem statement#
[1]You are given an integer array nums
of length n
where nums
is a permutation of the numbers in the range [0, n - 1]
.
You should build a set s[k] = {nums[k], nums[nums[k]], nums[nums[nums[k]]], ... }
subjected to the following rule:
The first element in
s[k]
starts with the elementnums[k]
.The next element in
s[k]
should benums[nums[k]]
, and thennums[nums[nums[k]]]
, and so on.We stop adding elements before a duplicate element occurs in
s[k]
.
Return the length of the longest set s[k]
.
Example 1#
Input: nums = [5,4,0,3,1,6,2]
Output: 4
Explanation:
nums[0] = 5, nums[1] = 4, nums[2] = 0, nums[3] = 3, nums[4] = 1, nums[5] = 6, nums[6] = 2.
One of the longest sets s[k]:
s[0] = {nums[0], nums[5], nums[6], nums[2]} = {5, 6, 2, 0}
Example 2#
Input: nums = [0,1,2]
Output: 1
Constraints:#
1 <= nums.length <= 10^5
.0 <= nums[i] < nums.length
.All the values of
nums
are unique.
Solution: Understanding the math behind#
A permutation[2] is a one-to-one mapping from a set of integers to itself.
The permutation on the set nums
in this problem is defined by the mapping i -> nums[i]
. For instance in Example 1, the permutation is defined as following:
0 -> 5,
1 -> 4,
2 -> 0,
3 -> 3,
4 -> 1,
5 -> 6,
6 -> 2.
You can always rearrange the definition of a permutation into groups of cyclic chains (factors).
0 -> 5, 5 -> 6, 6 -> 2, 2 -> 0,
1 -> 4, 4 -> 1,
3 -> 3
The set s[k]
in this problem is such a chain. In mathematics, it is called a cycle; because the chain (0, 5, 6, 2)
is considered the same as (5, 6, 2, 0)
, (6, 2, 0, 5)
or (2, 0, 5, 6)
in Example 1.
Assume you have used some elements of the array nums
to construct some cycles. To construct another one, you should start with the unused elements.
The problem leads to finding the longest cycle of a given permutation.
Code#
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int arrayNesting(const vector<int>& nums) {
int maxLen{0};
vector<bool> visited(nums.size());
for (auto& i : nums) {
if (visited[i]) {
continue;
}
int len{0};
// visit the cycle starting from i
while (!visited[i]) {
visited[i] = true;
i = nums[i];
len++;
}
maxLen = max(len, maxLen);
}
return maxLen;
}
int main() {
vector<int> nums = {5,4,0,3,1,6,2};
cout << arrayNesting(nums) << endl;
nums = {0,1,2};
cout << arrayNesting(nums) << endl;
nums = {0,2,1};
cout << arrayNesting(nums) << endl;
nums = {2,0,1};
cout << arrayNesting(nums) << endl;
}
Output:
4
1
2
3
Complexity#
Runtime:
O(n)
wheren
is the size of thenums
array.Extra space: much less than
O(n)
sincevector<bool>
is optimized for space efficiency.
Conclusion#
The problem of finding the length of the longest cycle in an array can be efficiently solved using a cycle detection approach. This solution efficiently detects cycles in the array by using a boolean array to mark visited elements.
By iterating through each element in the array and visiting the cycle starting from each unvisited element, the solution identifies the length of each cycle and updates the maximum length accordingly. This approach ensures that each cycle is visited only once and maximizes the length of the longest cycle in the array.