해결된 질문
작성
·
249
1
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
M = Integer.parseInt(br.readLine());
graph = new boolean[N][N];
visited = new boolean[N];
int x, y;
for (int i=0; i<=M; i++) {
StringTokenizer tokenizer = new StringTokenizer(br.readLine());
x = Integer.parseInt(tokenizer.nextToken())-1;
y = Integer.parseInt(tokenizer.nextToken())-1;
graph[x][y] = true;
graph[y][x] = true;
}
dfs(0);
System.out.println(answer - 1);
br.close();
}
void dfs(int index) {
visited[index] = true;
IntStream.range(0, M).forEach(i -> {
if (!visited[i] && graph[index][i]) dfs(i);
});
answer++;
}
위에처럼 저는 +1을하지않고(그래프에 0인덱스들은 사용을 안한다고 생각해서요.)
대신 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수를 입력받을 때 -1을해줘서 처리했는데요.
예제입력은 정상처리 되나 실제 제출해보면 런타임 에러 (ArrayIndexOutOfBounds)가 발생합니다. +1을 해줘야하는거같은데... 제가 생각한 배열사이즈, -1로 입력받기가 잘못된걸까요?
답변 1
2
zergcity님 안녕하세요 :)
작성하신 대로 하나 감소하는 것은 문제가 되지 않습니다! 제대로 동작하지 않는 이유는 크게 2가지가 있어요.
IntStream의 Range 버그
IntStream.range(0, M).forEach(i -> {
if (!visited[i] && graph[index][i]) dfs(i);
});
위에서 작성하신 코드는 0부터 M까지 반복하도록 되어있습니다.
그런데 실제 우리가 의도한 동작은 0부터 N까지 돌기를 원하는 거고, M은 간선의 개수이기 때문에 ArrayIndexOutOfBounds 런타임 에러가 발생하고 있습니다.
예를 들어 컴퓨터의 수는 3개라서 N = 3인데, 간선의 개수가 4개라면 위 IntStream에서 visited와 graph의 범위를 벗어나기 때문에 문제가 발생할 겁니다.
이걸 고쳐도 불량이 하나 더 있어요!
간선 입력 시 버그
for (int i=0; i<=M; i++) {
StringTokenizer tokenizer = new StringTokenizer(br.readLine());
x = Integer.parseInt(tokenizer.nextToken())-1;
y = Integer.parseInt(tokenizer.nextToken())-1;
graph[x][y] = true;
graph[y][x] = true;
}
위에 작성하신 코드에서 M개의 간선 정보를 입력 받으려면 i <= M
이 아니라 i < M
까지 돌아야 합니다.
위 코드는 M+1개의 간선을 기다리기 때문에 기대한대로 동작하지 못할 거니 주의가 필요해 보여요!
만약 단순 실수로 위 버그들이 발생한 거라면 변수명을 조금 더 명시적으로 작성해서 헷갈리지 않게 하는 게 좋을 것 같아요. M 대신 edgeCount를 사용했다면 첫 번째 버그가 발생할 확률이 조금 낮아질 것 같아요.
그리고 ArrayIndexOutOfBounds 에러가 발생했다는 건 결국 배열 접근 시 의도치 않게 큰 인덱스로 접근하는 것이 직접적인 원인이기 때문에, "배열 접근 중에 뭘 잘못하고 있지?"라는 식으로 접근해 보면 조금 더 빨리 디버깅 하고 코딩 테스트 중에도 빠르게 고칠 수 있을 것 같습니다!
혹시 더 필요하신 내용 있으면 알려주세요 :D