단어의 개수 - 1152번 (Java 풀이)
문제
영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열에는 몇 개의 단어가 있을까? 이를 구하는 프로그램을 작성하시오. 단, 한 단어가 여러 번 등장하면 등장한 횟수만큼 모두 세어야 한다.
입력
첫 줄에 영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열의 길이는 1,000,000을 넘지 않는다. 단어는 공백 한 개로 구분되며, 공백이 연속해서 나오는 경우는 없다. 또한 문자열은 공백으로 시작하거나 끝날 수 있다.
출력
첫째 줄에 단어의 개수를 출력한다.
예제 입력 1
The Curious Case of Benjamin Button
예제 출력 1
6
예제 입력 2
The first character is a blank
예제 출력 2
6
예제 입력 3
The last character is a blank
예제 출력 3
6
나는 이 문제를 처음 봤을 때 가장 먼저 떠올랐던 방법은 공백이 연속해서 나오지 않고 1개만 나오는걸 이용해 공백의 갯수를 세고 공백의 개수+1을 하면 문장을 이루는 단어의 개수를 구할 수 있을 거라 생각하여 문자열을 입력받고, 해당 문자열에서 공백의 갯수가 몇개인지 판단해 +1을 해주는 방법으로 풀어보았다.
package BEAKJOON_1152;
/*
날짜 : 2024.07.17.수
내용 : 백준 1152번 ( 단어의 개수)
*/
import java.util.*;
public class BEAKJOON_1152 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine().trim(); // 문자열 입력받기 + 양끝에 있는 스페이스바떄문에 생기는 오차는 trim을 활용해 잡아줌
int count = 0; // 공백문자수 카운팅하는 변수
for(int i=0; i<str.length(); i++) { // Character 클래스의 isWhitespace 메서드과 반복문을 활용하여 문자열을 이루는 문자들중 " "공백이 있는지 체크
if(String.valueOf(str.charAt(i)).matches("\\s")) {
count++; // 공백문자 카운팅하기
}
}
System.out.println(count+1); // 몇개의 단어로 이루어진건지 출력
}
}
출력값은 동일하게 나오지만 '메모리 초과'라고 뜨게 되었는데 이런경우는 처음이라 이제부터는 슬슬 메모리 까지 생각하며 풀어야 한다는 것에 이제부터가 진짜 알고리즘과 자료구조 공부의 시작인 건가를 느끼게 되었고, 왜 메모리 초과가 나는 건지에 대해 알아보기 위해 서칭해본 결과 각 문자마다 String 객체를 생성하는 부분에서 많은 에러가 발생하는 듯 보였다.그렇기에 String 객체로 변환하지않고 character 형태로 공백을 구별하는 방법으로 바꾸어 character.isWhitespace 메서드를 활용해 코드를 수정하였다.
package BEAKJOON_1152;
/*
날짜 : 2024.07.17.수
내용 : 백준 1152번 ( 단어의 개수)
*/
import java.util.*;
public class BEAKJOON_1152 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine().trim(); // 문자열 입력받기 + 양끝에 있는 스페이스바떄문에 생기는 오차는 trim을 활용해 잡아줌
int count = 0; // 공백문자수 카운팅하는 변수
for(int i=0; i<str.length(); i++) { // Character 클래스의 isWhitespace 메서드과 반복문을 활용하여 문자열을 이루는 문자들중 " "공백이 있는지 체크
if(Character.isWhitespace(str.charAt(i))) {
count++; // 공백문자 카운팅하기
}
}
System.out.println(count+1); // 몇개의 단어로 이루어진건지 출력
}
}
하지만 어째서인지 출력값은 동일하지만 틀렸다고 결과가 출력되어 잠시 뇌절이 왔고 다른 사람들의 블로그를 참고하여 다시 풀게되었다....
아래는 Scanner보다 처리하는 데이터의 양이 많아지면 많아질수록 BufferedReader의 성능이 더 좋다고 하여 BufferedReader로 Scanner를 대체하고 Character.isWhiteSpace를 Split으로 대체하여 다시 짜본 코드이다.
package BEAKJOON_1152;
/*
날짜 : 2024.07.17.수
내용 : 백준 1152번 ( 단어의 개수)
*/
import java.io.*;
public class BEAKJOON_1152 {
public static void main(String[] args) throws Exception {
// BufferredReader를 사용하기 위해 읽어들일 파일이 없거나 읽을 수 없는 경우에 대해 IOException을 throws로 예외처리
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// (System.in)에서 키보드를 통해byteSteam 형태로 입력받은 값을 InputStreamReader를 활용해 문자스트림형태로 변환시켜주고 BufferedReader를 통해 한꺼번에 데이터를 처리하여 데이터처리성능을 올림
String str = br.readLine().trim(); // 문자열 입력받기 + 양끝에 있는 스페이스바떄문에 생기는 오차는 trim을 활용해 잡아줌
int count = str.split(" ").length; // split()을 활용하여 공백으로 문자열을 나눠 새로운 배열로 저장될 때 해당 배열의 길이로 쪼개진 단어의 수를 측정
System.out.println(count); // 몇개의 단어로 이루어진건지 출력
br.close();
}
}
왜 오류가 계속 뜨는건지 몰라 멘탈이 바스라졌기에 같은 로직의 다른 사람의 코드를 아예 복붙해서 실행시켜본 결과 성공으로 떴고, 그 원인은 아래 코드처럼 사용자가 제대로 입력했는지확인하는 검증코드에 대한 로직을 짜지 않았기 때문이었다. 문제를 푸는데 있어서 검증 코드를 넣고 안넣고는 상관없다고 생각했는데 검증코드가 왜 꼭 들어가야하는지 이해하지 못하였지만, 문제를 푸는것이 아니여도 검증코드는 좋은 코드를 작성할 때 꼭 필요한 작업이기에 앞으로는 BufferedReader를 사용할 때 검증 코드를 넣어주는 습관을 길러보도록 하겠다...
package BEAKJOON_1152;
/*
날짜 : 2024.07.17.수
내용 : 백준 1152번 ( 단어의 개수)
*/
import java.io.*;
public class BEAKJOON_1152 {
public static void main(String[] args) throws Exception {
// BufferredReader를 사용하기 위해 읽어들일 파일이 없거나 읽을 수 없는 경우에 대해 IOException을 throws로 예외처리
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// (System.in)에서 키보드를 통해byteSteam 형태로 입력받은 값을 InputStreamReader를 활용해 문자스트림형태로 변환시켜주고 BufferedReader를 통해 한꺼번에 데이터를 처리하여 데이터처리성능을 올림
String str = br.readLine().trim(); // 문자열 입력받기 + 양끝에 있는 스페이스바떄문에 생기는 오차는 trim을 활용해 잡아줌
if (str.equals("")) { // 사용자가 문자열을 제대로 입력했는지 검증하기
System.out.println(0);
return;
}
int count = str.split(" ").length; // split()을 활용하여 공백으로 문자열을 나눠 새로운 배열로 저장될 때 해당 배열의 길이로 쪼개진 단어의 수를 측정
System.out.println(count); // 몇개의 단어로 이루어진건지 출력
br.close();
}
}