백준 1157번 자바
https://www.acmicpc.net/problem/1157
문제내용은 아래 더보기를 누르면 나온다.
알고리즘
알파벳 대소문자로 된 단어가 주어진다. ( 대소문자 구분하지 않는다!!! )
단어에서 가장 많이 사용된 알파벳을 출력한다. ( 출력은 대문자 )
동일하게 나오면 "?" 를 출력한다.
푸는 방법은 알파벳 숫자 26개만큼 배열을 만들어서 해당하는 배열값을 1+씩 해줘서 제일 높은 값 찾아야겠다.
1. int[26] 인 arr을 만든다.
2. 단어 str 을 받는다.
3. str의 길이만큼 반복한다.
3-1. str.charAt(i) 를 사용하여 문자 하나를 가져온다.
3-2. 문자가 소문자면 - 'a' 또는 - 97을 해준다.
3-3. 문자가 대문자면 - 'A' 또는 - 65를 해준다.
3-4. arr[문자를 뺀 값]++ 해준다.
4. int max = -1 을 만든다.
5. 26번 반복한다.
5-1. max보다 크다면 max에 값을 대입하고, (char)(현재 반복횟수값 + 65)을 index에 저장한다.
5-2. max보다 작다면 넘어간다.
5-3. max와 같다면 index에 "?"를 저장한다.
6. index를 출력한다.
풀이1
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class No_1157 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int[] arr = new int[26];
String str = br.readLine();
for (int i = 0; i < str.length(); i++) {
int str_char = str.charAt(i);
if (97 <= str_char && str_char <= 122) {
arr[str_char - 97]++;
} else {
arr[str_char - 65]++;
}
}
int max = -1;
char index = 0;
for (int i = 0; i < 26; i++) {
if (arr[i] > max) {
max = arr[i];
index = (char) (i + 65);
} else if (arr[i] == max) {
index = '?';
}
}
System.out.println(index);
}
}
알고리즘에 적었던 풀이대로 만들어보았다.
작성하다보니 다른 방법도 생각났다.
첫 for문을 문자길이만큼 반복해서 if문으로 걸러내는게 아니라 while문을 써본다면?
현재 한줄만 입력받는데 이걸 byte단위로 문자 1개를 계속읽다가 마지막에 없다면? IDE환경에서는 엔터를 누르게 될텐데
이 경우 엔터 = 줄바꿈 = IDE 인코딩값(아스키코드)으로는 10이 나오게 된다.
그렇다면 대문자 A = 65, 소문자 z = 122 이므로 while문을 만들 수 있게 된다.
그렇다면 풀이2에서 한번 시도해보자.
풀이2
import java.io.IOException;
public class No_1157 {
public static void main(String[] args) throws IOException {
int[] arr = new int[26];
int str_char = System.in.read(); // 첫 문자 받아오기
while (str_char > 64) { // A보다 크거나 같다면 계속 반복하기
if (str_char < 91) { // 대문자인가?
arr[str_char - 65]++;
} else { // 아니면 소문자이다
arr[str_char - 97]++;
}
str_char = System.in.read(); // 다음 문자 받아오기
}
int max = -1;
int index = 0;
for (int i = 0; i < 26; i++) {
if (arr[i] > max) { // max보다 값이 큰가?
max = arr[i];
index = i;
} else if (arr[i] == max) { // max와 같은가?
index = -2; // '?' = 63 이다.
}
}
System.out.println((char) (index + 65));
}
}
입력을 BufferedReader로 한줄입력이 아닌 바로 byte단위로 문자입력받기
for을 while문으로 바꾸기
단어 길이(str.length()) 와 단어에서 문자추출 (str.charAt(i))을 문자단위로 입력받으므로 없애기
두번째 for문 (출력 전)에서 계속 강제형변환으로 index에 값을 넣어줬는데 그것을 빼고 마지막 출력할때 char 강제형변환해서 출력하기
이렇게 풀이1에서 풀이2로 변경했는데 메모리와 시간이 엄청 단축됐다.
새삼스레 단순하게 받을수록 빠르게 내보내고 성능을 덜 잡아먹는다는 것을 체감하게 되었다.
자바에서는 스트림이 정말 중요한것 같다.
입출력에 대한 구조, for문과 while문의 반복문 구조를 열심히 공부해야할 듯 하다.
byte단위로 입력받다가 출력에 13과 10이 출력됐는데 이것은 무엇인가요?
일단 이것은 아스키코드값으로 변환하자면
13 = \r
10 = \n
이라는 의미이다.
\r은 Carriage Return(CR) 이란 의미이고, 이것은 줄의 끝에서 시작위치로 돌아간다는 뜻이다. (줄의 시작위치 이동)
\n은 Line Feed(LF) 이란 의미이고, 이것은 커서를 한칸 아래로 이동하여 새로운 라인을 추가한다는 뜻이다. (줄바꿈)
우리가 엔터(줄바꿈)를치면 어떤건 13과 10이 나오고 어떤건 10만 나올 때가 있다.
이것은 운영체제의 차이점인데 다음과 같다.
윈도우(Windows)는 CRLF
유닉스(Unix) 계열 OS(Linux와 macOS 등 포함)는 LF
맥(macOS 9 이전 버전)은 CR
즉, 자바에서는 운영체제에 맞게 자동으로 줄바꿈 문자를 변경해주는데 이 운영체제 차이점을 알고있으면 좋을듯하다.
'코딩테스트 > Java - 백준' 카테고리의 다른 글
[백준] 2908번 - Java(자바) (0) | 2022.02.23 |
---|---|
[백준] 1152번 - Java(자바) (0) | 2022.02.21 |
[백준] 2675번 - Java(자바) (0) | 2022.02.14 |
[백준] 10809번 - Java(자바) (0) | 2022.02.12 |
[백준] 11720번 - Java(자바) (0) | 2022.02.09 |