[Java] 초기화

Jung In Lee·2024년 12월 16일

JAVA

목록 보기
9/10

14500 테트로미노 문제를 풀던중 한가지 문제를 마주하였다.

바로 배열의 초기화에대한것.

자바에서 초기화는 다음과 같다.

boolean[][] visited = new boolean[N][M];

이 함수를 보고 여태 한 생각은 처음 메모리공간이 O(1)시간 만에 디폴드값으로 할당되는줄알았다. (부끄럽게도)

하지만 테트로미노를 풀던 중,

  1. 전역으로 정의된 visited
static boolean[][] visited;

visited = new boolean[N][M];
for (int i = 0; i < N; i++) { // 500
	for (int j = 0; j < M; j++) { // 500
		visited[i][j] = true;
		dfs(i, j, 1, map[i][j]);
		visited[i][j] = false;
	}
}
  1. 지역함수의 파라미터로 정의된 visited
        for (int i = 0; i < N; i++) { // 500
            for (int j = 0; j < M; j++) { // 500
                boolean[][] visited = new boolean[N][M];
                visited[i][j] = true;
                dfs(i, j, 1, map[i][j], visited);
            }
        }
        
    private static void dfs(int x, int y, int cnt, int sum, boolean[][] visited) {
        if (cnt == 4){
            max = Math.max(max, sum);
            return;
        }

        for (int d = 0; d < 4; d++) { // 4
            int nx = x + dx[d];
            int ny = y + dy[d];

            if (!isRange(nx, ny)) continue;
            if (!visited[nx][ny]) {
                visited[nx][ny] = true;
                dfs(nx, ny, cnt + 1, sum + map[nx][ny], visited);
                visited[nx][ny] = false;
            }
        }
    }

2번 코드에서 시간초과가 나는것을 마주했다.

그래서 두 차이점을 chatgpt로 알아본 결과..

네, 맞습니다. boolean[][] visited = new boolean[N][M]을 선언하면 내부적으로 다음과 같은 초기화 작업이 이루어집니다:

1. 초기화 동작

  • Java에서 배열은 선언과 동시에 기본값으로 초기화됩니다.
  • boolean[][] visited = new boolean[N][M];의 경우:
    • visited2차원 배열이므로, 내부적으로 N * M개의 boolean 값을 생성하고, 모두 기본값 false로 초기화합니다.

내부 동작:

  • 메모리 공간 할당:
    • O(N×M)의 메모리 공간이 할당됩니다.
  • 초기화:
    • 각 배열 요소를 기본값 false로 설정하며 O(N×M) 시간이 소요됩니다.

2. 왜 초기화가 필요한가?

Java는 안전한 초기값을 보장하기 위해 배열 선언 시 초기화를 자동으로 수행합니다.
이는:

  • 선언된 변수에 알 수 없는 값(garbage value)가 남아있는 것을 방지합니다.
  • boolean은 기본값이 false, int0, Objectnull 등으로 초기화됩니다.

3. 초기화 비용의 영향

  • 배열 크기가 클수록 초기화 작업에 소요되는 시간이 늘어납니다.
    • 예를 들어, (N = 500), (M = 500)이라면 (250,000)번의 기본값 설정이 이루어집니다.
  • 반복적으로 선언한다면 이 초기화 작업이 누적되어 성능에 영향을 미칠 수 있습니다.

4. 최적화 방법

  • 전역 변수 사용:
    • visited[][]를 한 번 선언하여 모든 탐색에 재사용하면, 배열 초기화 작업을 반복적으로 수행할 필요가 없습니다.
    • 탐색마다 visited[x][y] 값을 true/false로 변경하면서 활용합니다.
  • 배열 초기화 최소화:
    • 필요할 때만 특정 영역을 초기화하거나, Arrays.fill()을 이용해 특정 행만 초기화합니다.

5. 결론

  • 선언만으로도 O(N×M)번의 초기화 작업이 이루어지며, 이는 코드 실행 시간에 영향을 미칠 수 있습니다.
  • 배열을 반복적으로 생성하기보다는 전역으로 선언해 재사용하거나, 필요에 따라 부분 초기화를 수행하면 효율성을 높일 수 있습니다.

결론적으로 초기화를 할때 배열의 크기만큼 작업이 이루어진다는것이다.
따라서 O(1)이 아닌 O(N * M)만큼의 실행시간이 걸린다. 알고리즘을 풀때는 전역변수를 주로 사용하는것이 이와같은 이유인것같다.

profile
Software Developer

0개의 댓글