개발자는 기록이 답이다

[백준/BOJ][Java][1152] 단어의 개수 본문

알고리즘/백준

[백준/BOJ][Java][1152] 단어의 개수

slow-walker 2023. 8. 24. 20:56

2023.08.21 - [Java] - Java, String의 constant pool과 Heap의 차이

 

Java, String의 constant pool과 Heap의 차이

Java String 문자열? 순서를 가진 문자들의 집합 “쌍따옴표를 통해 나타낼 수 있음” 글자, 단어, 문장, 문서 등 문자로 구성된 자료형 // 기본 자료형 int var_integer = 10; double var_real - 3.141592; char var_ch

strong-park.tistory.com


https://www.acmicpc.net/problem/1152

 

1152번: 단어의 개수

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

www.acmicpc.net

내가 푼 풀이

- StringTokenizer의 countTokens()함수를 이용해서 매우 쉽게 풀었다.

 - 다른 사람들도 이렇게 풀었을 줄 알았는데, 이걸 사용안하고 분기처리를 해서 풀었더라..

- 근데 다른 사람 풀이가 이렇게 간단한 내 풀이보다 코드길이는 쪼~금 길지만, 메모리랑 시간이 거의 1/2배였다. 왜일까?

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

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

 

메모리 시간 언어 코드 길이
20548KB 180ms Java8 420B

 

 

다른 사람 풀이

- System.in.read()는 각 입력값에 대해 아스키 코드로 반환한다

int ch = System.in.read();
System.out.println("ch = " + ch); // -> 84 (int)

- 공백을 기준으로 ' '일때 cnt++하고, 마지막 '\n'일때 cnt ++해줘서 break일때 while문을 종료한다.

- pre를 word로 보면 되고, 공백이 아닐때 마다 word에 각 단어를 대입하고 공백이 아닌 경우에 카운트를 더한다.

import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        int cnt = 0;
        int pre = ' ';
        while (true) {
            int ch = System.in.read();
            if(ch == '\n') {
                if(pre != ' ') cnt++;
                break;
            }
            if(ch == ' ') {
                if(pre != ' ') cnt++;
            }
            pre = ch;
        }
        System.out.println(cnt);
    }
}
메모리 시간 언어 코드 길이
11508KB 104ms Java8 475B

 

 

다른 사람 풀이랑 비교

 

  1. StringTokenizer vs 문자 단위 읽기:
    • 첫 번째 코드에서는 StringTokenizer를 사용하여 입력 문자열을 공백을 기준으로 토큰으로 나누었습니다. StringTokenizer는 문자열을 토큰으로 나누는 작업에 매우 편리하지만, 내부적으로 문자열을 파싱하면서 문자열 객체와 관련된 작업이 수행되기 때문에 메모리 사용량이 더 커질 수 있습니다.
    • 두 번째 코드에서는 문자를 바이트 단위로 읽으면서 공백을 기준으로 토큰을 나누는 작업을 수행했습니다. 이는 문자열 파싱 없이 문자를 직접 처리하는 것으로 메모리 사용량이 더 작을 수 있습니다.
  2. System.in.read() 호출 횟수:
    • 첫 번째 코드에서는 한 줄을 통째로 읽은 뒤 StringTokenizer로 나누어 토큰 개수를 세기 때문에 입력을 모두 받은 뒤에야 토큰 개수를 확인할 수 있습니다.
    • 두 번째 코드에서는 문자를 읽으면서 토큰의 개수를 바로 세기 때문에 입력을 받으면서 동시에 토큰 개수를 확인할 수 있습니다.

따라서 두 번째 코드가 더 메모리 효율적이고, 문자 단위 읽기로 인해 입력을 받으면서 처리하는 방식으로 속도가 더 빠를 수 있습니다. 알고리즘적으로는 입력을 받으면서 토큰의 개수를 세는 두 번째 코드가 더 효율적인 접근 방식이라고 볼 수 있습니다.

 

 

참고 링크 :

 

https://devyoseph.tistory.com/141

 

Java: System.in.read(); 이해하기, 입력값을 알뜰하게 받기

System.in.read() Scanner, BufferedReader를 사용하지 않고 입력값을 받을 수 있다. 버퍼(InputStream)를 사용하기 때문에 효율적이며 IOException의 throw를 필수적으로 해주어야 한다. 문자를 하나씩만 가져올 수

devyoseph.tistory.com

https://kobalja2020.tistory.com/entry/Java-자바-기본-입-출력-Systeminread-에-대하여

 

Java - 자바 기본 입 출력/ System.in.read(); 에 대하여

오늘은 inputstream에 대하여 찾아보다가 자바 기본 입출력과 System.in.read라는 구문에 대해 확실하게 알기 위하여 공부해보았습니다. ● 자바에서는 기본적으로 ASCII 코드 값이 입력됩니다. 아래의

kobalja2020.tistory.com