Posts [Java] 백준 #1316: 그룹 단어 체커 (단계별 풀이)
Post
Cancel

[Java] 백준 #1316: 그룹 단어 체커 (단계별 풀이)

문제

그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속해서 나타나고, kin도 k, i, n이 연속해서 나타나기 때문에 그룹 단어이지만, aabbbccb는 b가 떨어져서 나타나기 때문에 그룹 단어가 아니다.

단어 N개를 입력으로 받아 그룹 단어의 개수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 단어의 개수 N이 들어온다. N은 100보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 단어가 들어온다. 단어는 알파벳 소문자로만 되어있고 중복되지 않으며, 길이는 최대 100이다.

출력

첫째 줄에 그룹 단어의 개수를 출력한다.

예제

입력1

1
2
3
4
3
happy
new
year

출력1

1
3

입력2

1
2
3
4
5
4
aba
abab
abcabc
a

출력2

1
1

풀이

1단계: int 배열 이용

  • 처음 제출한 답변
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
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = Integer.parseInt(sc.next());
    int count = n;

    for (int i = 0; i < n; i++) {
      String str = sc.next();
      int[] arr = new int[26];
      for (int j = 0; j < str.length(); j++) {
        if (arr[str.charAt(j) - 'a'] == 0) {
          arr[str.charAt(j) - 'a']++;
        } else if (j > 0 && str.charAt(j) != str.charAt(j - 1)) {
          count--;
          break;
        }
      }
    }
    System.out.println(count);
    sc.close();
  }
}

  • int 배열은 각 요소가 0인지 아닌지만 체크하는 용도로 사용하기 때문에, boolean 배열을 사용하는 게 더 적합해 보인다.

2단계: boolean 배열 이용

  • boolean 배열의 초기값은 false이다.
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
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = Integer.parseInt(sc.next());

    int count = n;
    for (int i = 0; i < n; i++) {

      String str = sc.next();
      boolean[] arr = new boolean[26];

      for (int j = 0; j < str.length(); j++) {
        if (arr[str.charAt(j) - 'a'] == false) {
          arr[str.charAt(j) - 'a'] = true;
        } else if (j > 0 && str.charAt(j) != str.charAt(j - 1)) {
          count--;
          break;
        }
      }
    }
    System.out.println(count);
    sc.close();
  }
}
  • 두 방법 모두 Outter loop가 한 번 돌 때 마다 배열이 생성되고 있는 게 문제다..
  • 메서드 호출로 바꿔보자.

3단계: 메서드 호출

  • 로직을 재사용할 수 있도록 메서드로 빼내보자.
  • 현재 문자를 변수 now에, 이전 문자를 변수 prev에 저장하였다.
    • 이때, 현재 문자의 인덱스(i)가 1 이상이어야만 prev이 존재할 수 있다. 따라서 i > 0일 때는 prev의 값을 str.charAt(i - 1)로, 아닐 때는 0으로 초기화해준다.
    • 만약 이를 고려하지 않으면 IndexOutOfBoundsException이 발생할 것이다
  • 함수 목적을 직관적으로 알아볼 수 있게 isGroupString()으로 명명했다.
  • 만약 그룹 단어가 맞다면 true를, 그룹 단어가 아니라면 false를 리턴한다.
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
29
import java.util.Scanner;

public class test1 {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = Integer.parseInt(sc.next());
    int count = 0;
    for (int i = 0; i < n; i++) {
      if (isGroupString(sc.next()))
        count++;
    }
    System.out.println(count);
    sc.close();
  }

  // 그룹 단어인지 체크하는 메서드
  static boolean isGroupString(String str) {
    boolean alpha[] = new boolean[26];
    for (int i = 0; i < str.length(); i++) {
      int now = str.charAt(i);
      int prev = (i > 0) ? str.charAt(i - 1) : 0;
      if (alpha[now - 'a'] == false)
        alpha[now - 'a'] = true;
      else if (now != prev)
        return false;
    }
    return true;
  }
}
  • 처음보다 훨씬 깔끔해져서 감동.. 이래서 함수로 빼내는구나..
This post is licensed under CC BY 4.0 by the author.

:book: 리팩토링 #1 (1): 메서드 분해와 기능 재분배

[Java] 백준 #2941: 크로아티아 알파벳

Loading comments from Disqus ...