[Programmers Lv.1] 모의고사
🔗 Link
💡 Idea
완전 탐색을 하는 쉬운 문제이다. 그런데 애먹은 부분이 있다면, 점수 계산을 끝낸 뒤에, 가장 높은 점수인 학생들을 모으는 과정이었다. 이 부분이 이 문제의 핵심 부분이 아닌데, 아래와 같이 코드가 길어지는 게 싫었다.
ArrayList<Integer> winners_list = new ArrayList<>();
int max_score = 0;
for(int i = 0; i < 3; i++){
max_score = Math.max(scores[i], max_score);
}
for(int i = 0; i < 3; i++){
if(scores[i] == max_score) winners_list.add(i+1);
}
int[] winners_array = new int[winners_list.size()];
for(int i = 0; i < winners_list.size(); i++){
winners_array[i] = winners_list.get(i);
}
return winners_array;
그래서 문제를 푼 이후에 stream을 이용하여 코드를 줄여보았다. 아직 stream으로 생각하는 방식이 익숙하지 않아 바로 떠올리기가 쉽지 않았다.
int max_score = Arrays.stream(scores).max().orElse(0);
int[] winners = IntStream.range(0,3).filter(i -> scores[i] == max_score).map(i -> i+1).toArray();
return winners;
🔑 Code
import java.util.*;
import java.util.stream.IntStream;
class Solution {
private static final int[][] rules = {
{1, 2, 3, 4, 5},
{2, 1, 2, 3, 2, 4, 2, 5},
{3, 3, 1, 1, 2, 2, 4, 4, 5, 5}
};
public int[] solution(int[] answers) {
int scores[] = {0,0,0};
for(int i = 0; i < answers.length; i++){
for(int j = 0; j < 3; j++){
if(rules[j][i % rules[j].length] == answers[i]) scores[j]++;
}
}
int max_score = Arrays.stream(scores).max().orElse(0);
int[] winners = IntStream.range(0,3).filter(i -> scores[i] == max_score).map(i -> i+1).toArray();
return winners;
}
}
🗨️ Side Notes
람다식 내부에서 지역 변수를 사용하려면 그 변수는
final이거나 effectively final이어야 한다.
현재 코드는 가능하다.
int maxScore = Arrays.stream(scores)
.max()
.orElse(0);
return IntStream.range(0, scores.length)
.filter(i -> scores[i] == maxScore)
.toArray();
maxScore를 선언한 이후 다시 바꾸지 않았기 때문이다.
이런 변수를 effectively final이라고 한다.
다음 코드는 컴파일되지 않는다.
int maxScore = 0;
for (int score : scores) {
maxScore = Math.max(maxScore, score);
}
return IntStream.range(0, scores.length)
.filter(i -> scores[i] == maxScore)
.toArray();
왜냐하면 maxScore가 반복문에서 계속 변경되기 때문이다.
컴파일러는 대략 다음과 같은 오류를 낸다.
Local variable maxScore defined in an enclosing scope
must be final or effectively final
이 경우 중간 변수를 하나 더 만들 수 있다.
int max = 0;
for (int score : scores) {
max = Math.max(max, score);
}
int maxScore = max;
return IntStream.range(0, scores.length)
.filter(i -> scores[i] == maxScore)
.map(i -> i + 1)
.toArray();
maxScore는 선언 후 변경되지 않으므로 람다에서 사용할 수 있다.
하지만 이 문제에서는 Stream으로 최댓값까지 구하면 더 간단하다.
int maxScore = Arrays.stream(scores)
.max()
.orElse(0);