[Algorithm/Java] 백준 2920번 - 음계
https://www.acmicpc.net/problem/2920
📌 문제
문제 유형
- 구현
문제 설명
- 8개의 숫자가 주어졌을 때, 이 숫자가 1부터 8까지 순서대로 증가하면 “ascending”,
- 8부터 1까지 감소하면 “descending”,
- 둘 다 아니면 “mixed”를 출력
입출력 예시
입력
1 2 3 4 5 6 7 8
출력
ascending
🔍 문제 풀이
- 입력값을
StringTokenizer
로 한 줄에 받아서List<Integer>
에 저장 - 오름차순/내림차순 기준 리스트와 비교하여 결과 출력
리스트 값 접근 방식
자료구조 | 접근 방식 | 예시 |
---|---|---|
배열 | arr[i] |
arr[0] |
리스트 | list.get(i) |
list.get(0) |
리스트는 클래스이므로 get()
메서드로 접근해야 한다.
입력 방식: split() vs StringTokenizer
split()
String[] arr = br.readLine().split(" ");
- 한 줄 입력 가능:
1 2 3 4
- 공백 기준으로 잘라서 배열에 저장
- 정규식 기반 분리도 가능 (
split("\\s+")
등)
StringTokenizer
for (int i = 0; i < 4; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
list.add(Integer.parseInt(st.nextToken()));
}
위 코드는 한 줄 입력이 가능할 것처럼 보이지만, 실제로는 아래처럼 입력을 줄마다 받아야 동작함
1
2
3
4
그래서 hasMoreTokens()
을 같이 사용해야 한 줄 입력 처리가 가능
StringTokenizer st = new StringTokenizer(br.readLine());
while (st.hasMoreTokens()) {
list.add(Integer.parseInt(st.nextToken()));
}
- 입력: 1 2 3 4
- 공백 기준으로 나눈 토큰을 하나씩 꺼내는 구조
hasMoreTokens()
는 남은 토큰이 있는지 확인하는 메서드true
일 때만nextToken()
으로 꺼냄
🤖 split() vs StringTokenizer 차이 정리
항목 | split() |
StringTokenizer |
---|---|---|
리턴 타입 | 문자열 배열 (String[] ) |
토큰을 꺼내는 반복 구조 |
구분자 | 정규식 가능 (예: split("\\s+") ) |
단순 구분자 (보통 공백)만 처리 |
반복 방식 | 배열 반복 (for , for-each ) |
hasMoreTokens() + nextToken() 사용 |
속도 | 약간 느림 (배열 생성 비용 있음) | 약간 빠름 (필요할 때 꺼냄) |
유연성 | 높음 (정규식으로 다양한 패턴 분리 가능) | 낮음 (단순 구조에 적합) |
💻 전체 코드
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
List<Integer> nums = new ArrayList<>();
StringTokenizer st = new StringTokenizer(br.readLine()); // 한 줄 입력
while(st.hasMoreTokens()){
nums.add(Integer.parseInt(st.nextToken()));
}
if(isASC(nums)){
System.out.println("ascending");
} else if(isDES(nums)){
System.out.println("descending");
}
else{
System.out.println("mixed");
}
}
public static boolean isASC(List<Integer> nums){
for(int i=0; i<nums.size()-1; i++){
if (nums.get(i) > nums.get(i+1)){
return false;
}
}
return true;
}
public static boolean isDES(List<Integer> nums){
for(int i=0; i<nums.size()-1; i++){
if (nums.get(i) < nums.get(i+1)){
return false;
}
}
return true;
}
}
💭 배운 점
- 입력을 받을 때
split()
대신StringTokenizer
를 사용해서 풀어보고 싶었다. - 처음엔 그냥
StringTokenizer
만 사용해서br.readLine()
을 반복하며 값을 받았는데, 그렇게 하면 사용자 입력이 아래처럼 줄바꿈 형태로 입력되어야만 작동한다는 걸 알게 됐다.
1
2
3
4
하지만 내가 생각했던 입력 방식은 한 줄에 숫자들을 띄어쓰기로 구분해서 입력하는 것이었다.
1 2 3 4
처럼 입력하고 싶었던 거다.
그래서 StringTokenizer
를 사용할 때도 단순히 반복문을 돌리는 게 아니라, hasMoreTokens()
를 활용해서 한 줄에 있는 모든 숫자를 끝까지 하나씩 읽어야 한다는 걸 깨달았다.
StringTokenizer
를 쓰되, 한 줄 입력 + hasMoreTokens()
반복을 함께 사용해야 내가 의도한 입력 형태대로 데이터를 받을 수 있었다.
🔁 복습 템플릿
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
List<Integer> nums = new ArrayList<>();
StringTokenizer st = new StringTokenizer(br.readLine()); // 한 줄 입력
// 입력값 저장
if(isASC(nums)){
System.out.println("ascending");
} else if(isDES(nums)){
System.out.println("descending");
}
else{
System.out.println("mixed");
}
}
public static boolean isASC(List<Integer> nums){
for(int i=0; i<nums.size()-1; i++){
if (nums.get(i) > nums.get(i+1)){
return false;
}
}
return true;
}
public static boolean isDES(List<Integer> nums){
for(int i=0; i<nums.size()-1; i++){
if (nums.get(i) < nums.get(i+1)){
return false;
}
}
return true;
}
}
댓글남기기