문제 설명
길이가 N이고 인덱스가 0부터 시작하는 배열 A가 있다고 가정해 보겠습니다. 이 배열은 0부터 N-1까지의 모든 정수를 정확히 한 번씩 포함합니다. 우리가 구해야 하는 것은 다음 규칙을 따르는 집합 S의 최대 길이입니다.
S[i] = {A[i], A[A[i]], A[A[A[i]]], ...}집합 S는 인덱스 i에서 시작하여 첫 원소로 A[i]를 선택하고, 그다음에는 A[A[i]], 그 뒤에는 A[A[A[i]]]를 차례로 추가합니다. 이 과정을 계속 반복하다가 S 안에 중복된 값이 나타나기 직전에 추가를 멈춥니다.
예시
배열이 A = [5,4,0,3,1,6,2]일 때 정답은 4입니다. 인덱스 0에서 시작하면 다음과 같은 흐름을 따릅니다.
- A[0] = 5
- A[5] = 6
- A[6] = 2
- A[2] = 0
- 그다음 값은 A[0] = 5로 이미 집합에 존재하므로 탐색 종료
따라서 집합 S = {5, 6, 2, 0}의 길이인 4가 됩니다. 같은 방식으로 인덱스 1에서 시작하면 {4, 1}(길이 2), 인덱스 3에서 시작하면 {3}(길이 1)이 되므로, 전체 최댓값은 4입니다.
접근 방법: DFS 활용
이 문제는 본질적으로 각 인덱스에서 출발하는 순환(cycle)을 찾는 것과 같습니다. 깊이 우선 탐색(DFS)을 사용하면 효율적으로 해결할 수 있으며, 알고리즘 단계는 다음과 같습니다.
- dfs 함수 생성: node, arr 배열, 경로를 담을 v 배열, 방문 여부를 기록할 visited 집합을 매개변수로 받습니다.
- node가 이미 방문한 노드라면 즉시 반환합니다.
- node를 v에 삽입하고 visited에 방문 표시를 합니다.
- dfs(arr[node], arr, v, visited)를 재귀 호출합니다.
- 메인 로직: ret := 0, n := nums의 크기로 초기화하고 visited 집합을 만듭니다.
- i를 0부터 n-1까지 순회합니다.
- 새로운 배열 v를 생성합니다.
- nums[i]를 아직 방문하지 않았다면 dfs(nums[i], nums, v, visited)를 호출합니다.
- ret을 ret과 v의 크기 중 더 큰 값으로 갱신합니다.
- 최종적으로 ret을 반환합니다.
한 번 방문한 노드는 다른 시작점에서 다시 탐색할 필요가 없습니다. 어느 지점에서 시작하든 결국 같은 순환에 속하기 때문입니다. visited 집합 덕분에 각 노드를 한 번씩만 확인하면 되므로, 전체 시간 복잡도는 O(N), 공간 복잡도 역시 O(N)입니다.
C++ 구현 예제
아래 코드를 통해 실제 구현을 확인해 보겠습니다.
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
void dfs(int node, vector <int>& arr, vector <int>& v, set <int>& visited){
if(visited.count(node)) return;
v.push_back(node);
visited.insert(node);
dfs(arr[node], arr, v, visited);
}
int arrayNesting(vector<int>& nums) {
int ret = 0;
int n = nums.size();
set <int> visited;
for(int i = 0; i < n; i++){
vector <int> v;
if(!visited.count(nums[i]))dfs(nums[i], nums, v, visited);
ret = max(ret, (int)v.size());
}
return ret;
}
};
main(){
vector<int> v = {5,4,0,3,1,6,2};
Solution ob;
cout << (ob.arrayNesting(v));
}입력
[5,4,0,3,1,6,2]
출력
4
마무리
배열 중첩 문제는 배열의 값이 곧 다음 인덱스가 되는 특성 때문에 자연스럽게 순환 구조를 형성합니다. DFS와 방문 처리를 조합하면 모든 순환을 한 번씩만 확인하면 되므로 선형 시간 안에 답을 구할 수 있습니다. 재귀 호출이 부담스럽다면 명시적인 스택을 사용하는 반복형 DFS로도 동일하게 구현할 수 있으니 함께 연습해 보시기 바랍니다.