본문 바로가기

알고리즘/문자열

[자바]백준 1152번 단어의 개수 [문자열][엄탱]

728x90

안녕하세요. 개발자 엄탱입니다.
이 글은 알고리즘을 공부하면서 공부 기록용입니다.
그래서 설명마다 일기용으로 편하게 작성하여 반말 형식으로 작성하려고 합니다.
그리고 보시다가 더 좋은 방법이나 잘 못 알고 있는 내용이 있다면 알려주시면 정말 감사하겠습니다.
좋은 하루 되세요 :)

 

문제

영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열에는 몇 개의 단어가 있을까? 이를 구하는 프로그램을 작성하시오. 단, 한 단어가 여러 번 등장하면 등장한 횟수만큼 모두 세어야 한다.

 

입력

첫 줄에 영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열의 길이는 1,000,000을 넘지 않는다. 단어는 공백 한 개로 구분되며, 공백이 연속해서 나오는 경우는 없다. 또한 문자열은 공백으로 시작하거나 끝날 수 있다.

 

출력

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

 

예제

알고리즘 분류

  • 구현
  • 문자열

문제 설명

쉽게 말해 문자열에서 단어의 개수를 체크하는 것이다.

 

풀이

해당 문제는 공백과 단어만 구분 지으면 되는 문제이고 여러 방식으로 풀어보는 게 추후에 좋을 것 같아 3가지 정도 방법을 사용했다.

  1. 내장 함수를 사용하지 않고 그냥 기본 반복문만 사용한 풀이
  2. StringTokenizer을 사용한 풀이
  3. split()과 trim()을 사용한 풀이

부가 설명은 각 코드 아래에 작성하겠다.

 

코드1 (기본 반복문만 사용한 풀이)

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        
        int count = 0;
        
        boolean isPrevStr = false;
        
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) != ' ' && !isPrevStr) {
                isPrevStr = true;
                count++;
            } else if (s.charAt(i) == ' ') {
                isPrevStr = false;
            }
        }
        
        System.out.println(count);
        br.close();
    }
}

코드 풀이

'그냥 단어 나오면 카운팅 해주자'와 같이 쉽게 유추할 수 있는 방법이다.

단, 위와 같이 하면 단어별로 체크하는게 아니라 알파벳 하나하나 공백 하나하나 체크하게 된다.

그래서 카운팅 해준 단어의 알파벳은 그냥 넘겨야 하는게 포인트다.

현재 알파벳이 카운팅 해준 단어의 알파벳인지 알 수 있는 boolean 타입 변수 하나를 준비해 주자.

그 후 풀이 방식은 이렇다.

  1. 공백을 만나면 이전 문장이 알파벳이 아니고 공백이었으니, isPrevStr(이전문장이 알파벳인가요?)를 false 해주면 된다.
  2. 알파벳을 만나면 이전 문장이 알파벳이 아니고 공백(false)였으면 카운팅(+)해주고 아니면 무시하면 된다.

 

코드2 (StringTokenizer을 사용한 풀이)

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        
        System.out.println(st.countTokens());
        br.close();
    }
}

코드 설명

이건 그냥 StringTokenizer를 사용하여 푼 방식이다.

 

 

코드3 (split()과 trim()을 사용한 풀이)

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine().trim();
        
        if (s.equals("")) {
            System.out.println(0);
            return;
        }
        
        int count = s.split(" ").length;
        System.out.println(count);
        br.close();
    }
}

코드 설명

split을 사용한 경우에는 몇 가지 주의할 점이 있다.

  1. 앞 뒤 공백이 있는 경우
  2. 문장이 공백만 있는 경우

사실, 1번 같은 경우는 앞에 공백만 신경 써주면 된다.

이유는 아래와 같다.

String s = "  d d "; // 앞에 공백이 2개이다.
String[] ss = s.split(" ");

System.out.println(ss.length); // 출력: 4

for (String item: ss) {
    System.out.print(item + ", "); // 출력: , , d, d, 
}

System.out.println();

그렇기 때문에 trim()으로 앞 뒤 공백을 제거해 주는 것이다.

 

2번에서 문장이 공백만 있는 경우를 주의해야 하는 이유는 trim()을 써주고 나면 문자열이 ""로 되어있어 split을 사용하면 자기 자신으로 채워지게 된다. 즉, split을 공백을 기준으로 쪼개면 자기 자신인 ""로 길이가 1이 되기 때문에 문제가 된다. 

이런 경우에는 그냥 조건문으로 걸러주면 된다.

728x90