최근 프로그래머스 Java 도서 를 구매하여 매일 한 문제씩 풀기 시작했습니다.

전반적으로 Level 1에서 Level 3까지의 문제들이 책에 나왔으며, 이 과정에서 문제 풀이 방법과 몇 가지 팁을 공유하고자 합니다.

알고리즘 문제 풀이 방법

아래의 내용은 주관적이며, 저도 때때로 그냥 풀 때도 있지만.. 아래와 같이 문제를 풀면 좋을 것 같다 생각합니다..!

알고리즘 문제를 효과적으로 풀기 위해서는 체계적인 접근 방식이 필요합니다. 다음은 제가 사용하는 알고리즘 문제 풀이 방법입니다.

  1. 문제 이해 및 분석: 주어진 문제를 철저히 분석하고, 해결을 위해 필요한 알고리즘과 자료구조를 선택합니다.

  2. 코드 작성 및 테스트: 문제 해결을 위한 코드를 작성한 후, 다양한 테스트 케이스를 통해 코드의 정확성과 효율성을 검증합니다.

  3. 해설 확인: 문제를 푼 후, 해설을 통해 다른 접근 방법이나 최적화 방법을 학습하고, 자신의 코드와 비교해 개선점을 찾습니다.

  4. 코드 리뷰 및 개선: 해설을 참고하여 작성한 코드를 다시 검토하고, 개선할 부분을 수정합니다.

  5. 문제 정리: 문제를 풀고 난 후, 프로그래머스 사이트에서 문제를 정리하고, 풀이 과정을 Github 기록했습니다. 특히 어려웠던 문제는 README에 체크하여 나중에 복습할 때 참고하면 좋을 것 같습니다.

추가 팁

  • 시간 제한 설정: 문제를 풀 때 적절한 시간 제한을 설정하면 시간 낭비를 줄이고 더 많은 문제를 풀 수 있습니다. 예를 들어, 한 문제당 30분 이상 고민하지 않기로 규칙을 정합니다. Focus To do 프로그램을 이용하면 조금 더 집중하기 쉬울 수 있습니다.

  • 코드 리뷰: 다른 사람의 코드를 읽고 리뷰하는 것도 유익합니다. 이를 통해 새로운 접근 방식을 배우고, 코드의 가독성과 효율성을 향상시킬 수 있습니다.

  • 자동완성 도구 사용 자제: 알고리즘 문제를 풀 때는 자동완성 도구 사용을 자제합니다. 자동완성에 의존하면 기본 개념과 코딩 능력을 향상시키는 데 방해가 될 수 있기 때문입니다. 직접 코드를 작성하며 논리적 사고와 문제 해결 능력을 기르는 것이 중요합니다.

  • 꾸준한 연습: 알고리즘 문제 해결 능력은 꾸준한 연습을 통해 향상됩니다. 매일 일정 시간을 할애하여 문제를 풀어보는 습관을 기르는 것이 좋습니다.

알고리즘 패턴

문제를 풀다 보면 다양한 알고리즘 패턴이 존재함을 알 수 있습니다. BFS, DFS, 탐욕 알고리즘 등 다양한 패턴을 통해 문제를 해결할 수 있습니다.

또한, 문제를 풀 때는 어느 정도 템플릿을 사용하는 것이 도움이 됩니다. 아래는 문제를 풀다보면 자주 사용하는 템플릿을 정리했습니다.

  1. DFS (Depth-First Search) 깊이 우선 탐색은 그래프나 트리의 노드를 깊이 우선으로 탐색하는 알고리즘입니다. 하나의 경로를 끝까지 탐색한 후, 다른 경로를 탐색합니다.

경로가 매우 긴 경우에 효과적입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 private static int[] dx = {0, 1, 0, -1};
 private static int[] dy = {1, 0, -1, 0};

 public void search(int[][] grid) {
     int rows = grid.length;
     int cols = grid[0].length;
     for (int i = 0; i < rows; i++) {
         for (int j = 0; j < cols; j++) {
             if (grid[i][j] == 1) {
                 dfs(grid, i, j);
             }
         }
     }
 }

 private void dfs(int[][] grid, int x, int y) {
     grid[x][y] = -1; // 방문 표시
     for (int i = 0; i < 4; i++) {
         int nx = x + dx[i];
         int ny = y + dy[i];
         if (nx >= 0 && ny >= 0 && nx < grid.length && ny < grid[0].length && grid[nx][ny] == 1) {
             dfs(grid, nx, ny);
         }
     }
 }
  1. BFS (Breadth-First Search) 너비 우선 탐색은 그래프나 트리의 노드를 너비 우선으로 탐색하는 알고리즘입니다.

시작 노드와 같은 깊이의 노드들을 먼저 탐색한 후, 다음 깊이의 노드들을 탐색합니다.

최단 경로 탐색에 유리합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 private static int[] dx = {0, 1, 0, -1};
 private static int[] dy = {1, 0, -1, 0};

 public int bfs(int[][] grid, int startX, int startY) {
     Queue<int[]> queue = new LinkedList<>();
     queue.offer(new int[]{startX, startY});
     grid[startX][startY] = -1; // 방문 표시
     int steps = 0;

     while (!queue.isEmpty()) {
         int size = queue.size();
         for (int i = 0; i < size; i++) {
             int[] point = queue.poll();
             int x = point[0], y = point[1];
             for (int j = 0; j < 4; j++) {
                 int nx = x + dx[j];
                 int ny = y + dy[j];
                 if (nx >= 0 && ny >= 0 && nx < grid.length && ny < grid[0].length && grid[nx][ny] == 1) {
                     queue.offer(new int[]{nx, ny});
                     grid[nx][ny] = -1; // 방문 표시
                 }
             }
         }
         steps++;
     }

     return steps;
 }

알고리즘 문제를 풀 때 위와 같은 템플릿을 사용하면 좋습니다.

문제의 유형에 따라 적절한 알고리즘과 자료구조를 선택하고, 이를 기반으로 문제를 해결해 나가는 것이 중요합니다.

또한, 다양한 예제를 풀어보며 다양한 접근 방식을 익히는 것도 큰 도움이 될 것이라 생각됩니다.

느낀점

알고리즘 문제를 풀면서 어려움을 겪기도 했지만, 꾸준한 연습을 통해 성장할 수 있었습니다.

특히 Level 2까지는 어느 정도 풀었지만, Level 3 이상부터는 상당한 난이도를 느꼈습니다. 그래도 계속 문제를 풀다 보니 알고리즘 문제마다 특정 패턴이 있다는 것을 알게 되었습니다.

문제를 풀고 다른 사람들의 풀이를 보면서 “어떻게 저런 생각을 할 수 있을까?“라는 고민을 자주 하게 되었고, 이 과정에서 새로운 시각과 접근 방법을 배울 수 있었습니다.