다음 문제는 "실패율"이다.
(문제 출처 : 프로그래머스 https://school.programmers.co.kr/learn/courses/30/lessons/42889)
프로그래머스는 블로그 게재시 문제 여지가 있어
자세한 내용 없이 문제 제목과 링크로 대체합니다.
책에서 권장 시간 60분이랬는데 넘긴 듯
다음에는 시간도 재면서 풀어봐야겠다.
입출력 예시를 보면,
스테이지 수는 5개이고 총 8명의 사용자가 있습니다.
스테이지별로 아직 클리어 하지 못한 사용자와 도전한 사용자 수를 보면
스테이지 번호 | 클리어 못한 | 도전한 사용자 | 실패율 |
1 | 1 | 8 | 1/8 |
2 | 3 | 7 | 3/7 |
3 | 2 | 4 | 2/4 |
4 | 1 | 2 | 1/2 |
5 | 0 | 1 | 0/1 |
스테이지가 올라갈수록 클리어 못한 사용자의 수를 빼야 도전한 사용자의 수가 나온다!
그리고 나중에 출력은 실패율이 높은 스테이지부터 낮은 스테이지 순으로,
만약 실패율이 0으로 같다면 스테이지 번호가 낮은 것부터 높은 순으로 하라고 되어 있다.
헤매긴 했지만 그래도 혼자서 성공해 낸 내 코드 흐름을 보면
1) 스테이지별 실패율 계산을 위해 fail 이라는 배열을 하나 만들었다
실패율 계산에 나누기가 들어가서 실수형 double을 택함
2) 배열 fail의 순서(i+1)가 스테이지의 순서니까,
stages 배열을 돌면서 해당 스테이지를 클리어 못한 사용자를 카운트했다.
if (stages[j] == i+1) c++;
3) 그리고 실패율을 계산해서(c/u), fail 배열에 저장했다.
만약 클리어 못한 사용자가 없으면 실패율은 0이니까 바로 0으로 저장해 줬다.
4) 그리고 도전한 사용자 수에서 현재 스테이지에 남아있는 사용자 수(u-c)를 빼줬다.
스테이지 번호 fail[i] |
클리어 못한 사용자 stages[j]의 수 == i+1 c로 카운트 올림 |
도전한 사용자 u |
실패율 c/u로 계산 fail에 저장 |
5) 그리고 스테이지 순서대로 실패율을 저장해 놨기 때문에
clone 해서 sort로 내림차순 정렬을 했다.
근데 내가 사용한 배열은 기본 primitive 타입 double 이라서
Collections.reverseOrder()를 쓰기 위해 래퍼 wrapper 타입으로 형 변환을 해줬다.
6) 그리고 기존 배열과 제일 높은 순으로 정렬된 배열을 비교하면서
스테이지 순서를 조건에 맞게 fail_s 배열에 추가해 줬다.
실제로 작성한 코드는 이렇다
import java.util.*;
class Solution {
public int[] solution(int N, int[] stages) {
int[] answer = {};
// 스테이지 번호로 멈춘 수를 카운트
int s = N;
int u = stages.length; // 유저 모수 계산용
double[] fail = new double[s]; // 실패율 계산용 배열
// 스테이지별 실패율을 계산하면서, 전체 인원수를 줄여나감
for (int i=0; i<fail.length; i++){
int c=0;
for (int j=0; j<stages.length; j++){
if (stages[j] == i+1){ // 스테이지는 1번부터라 i+1
c++; // 해당 스테이지에 있는 사용자만 세기
}
}
if (c==0) {fail[i]=0;}
else {fail[i] = (double) c/u;}
u = u - c;
}
// 실패율을 비교해서 높은 스테이지 >> 낮은 스테이지. 실패율이 0이면 오름차순으로
double[] clone = fail.clone();
Double[] cd = Arrays.stream(clone).boxed().toArray(Double[]::new);
Arrays.sort(cd, Collections.reverseOrder());
ArrayList<Integer> fail_s = new ArrayList<>();
for (int i=0; i<cd.length; i++){
for(int j=0; j<fail.length; j++){
if (cd[i] == fail[j]){
fail_s.add(j+1);
fail[j] = -1;
break;
}
}
}
answer = fail_s.stream().mapToInt(Integer::intValue).toArray();
return answer;
}
}
이것보다 더 예쁘고 간단하게 코드짤 수 있을 것 같은데... 모르겠다 ㅋ
암튼 이 코드에서 배운 점은
내림차순 정렬은 일단 Arrays.sort(배열명, Collections.reverseOrder())을 사용한다.
하지만 기본 타입 배열에는 적용이 불가능하다.
*기본 타입: byte, char, double, short, long, int, float ...
그래서 래퍼 클래스로 만든 다음(boxing) 정렬해야 한다.
*래퍼 클래스: 기본 자료형의 데이터를 인스턴스(객체)로 만들기 위해 사용하는 클래스
Byte, Character, Double, Short, Long, Int, Float ...
double[] clone = fail.clone();
Double[] cd = Arrays.stream(clone).boxed().toArray(Double[]::new);
내가 공부 중인 책에서는
스테이지별 도전자 수/실패한 사용자 수를 추출하고,
그리고 해쉬 맵을 사용 해서 풀었더라
대략적인 흐름만 따라가 보자면
// 스테이지별 도전자 수를 구하는 부분
// 0번째 인덱스는 사용하지 않고, 마지막 스테이지까지 클리어한 N+1 고려
int[] chal = new int[N+2];
for 문
// 스테이지별 실패한 사용자 수 계산
// 해쉬맵의 키는 스테이지 번호, 값은 실패율
HashMap<Integer, Double> fails = new HashMap<>();
double total = stages.length;
// 각 스테이지를 순회하며 실패율 계산
for (int i = 1; i <= N; i++){
if 도전한 사람이 없는 경우 {fails.put(i, 0.);}
}
else{ // 있는 경우에는 실패율 계산
fails.put(i, chal[i] / total);
현재 스테이지 인원 빼기
}
// 실패율이 높은 스테이지부터 내림차순 정렬하기
return fails.entrySet().stream().sorted((oa, o2)
-> Double.compare(o2.getValue(), o1.getValue())).mapToInt(HashMap.Entry::getKey).toArray();
자세한 건 책을 직접 확인하세요
책 이름은 "코딩 테스트 합격자 되기: 자바편"입니다.
해쉬맵은
데이터를 추가할 때는 put(key, value)
모든 데이터 삭제할 때는 clear()
remove(key)는 key와 일치하는 기존 데이터 삭제
remove(key, value)는 key와 value가 동시에 일치하는 데이터 삭제
entrySet() : 모든 key-value 매핑 데이터를 가진 set를 반환
자바 스트림 Stream은 Java 8부터 추가된 기술로 람다를 활용해 배열과 컬렉션을 함수형으로 간단하게 처리
최종 연산 전까지 중간 연산을 수행하지 않는다.
작업을 내부 반복으로 처리한다.
.filter() > 스트림 내 요소들을 하나씩 평가해 걸러내는 if문의 역할
.sort() > 스트림 내 요소들을 정렬하는 작업. Comparator 사용
.distinct() > 중복 제거
List<String> list = Arrays.asList("a","b","c");
// filter
Stream<String> stream = list.stream()
.filter(list -> list.contains("a"));
// 'a'가 들어간 요소만 선택 [a]
// sort
Stream<String> stream = list.stream()
.sorted() // [a,b,c] 오름차순 정렬
.sorted(Comparator.reverseOrder()) // 내림차순
List<String> list = Arrays.asList("a","bb","ccc");
Stream<String> stream = list.stream()
.sorted(Comparator.comparingInt(String::length)) // [ccc,bb,a] 문자열 길이로 정렬
자바가 가능한 곳이 더 많아서 자바로 골랐는데
파이썬 할 걸 그랬나 자바 왜케 낯설어짐 ;;
아무튼 프로그래머스 되게 좋아졌다.
이렇게 내가 푼 문제 기반으로 Problem Solving 평가 리포트도 주더라
갓 시작한 인간이라 5개 밖에 안품...
나중에 성장하는 모습 비교해서 또 포스팅해야지
카테고리/레벨별로 상세하게 알려준다.
꾸준하게 문제 풀이 하면 내가 어디가 취약한지 파악 가능할듯
그리고 데이터 쌓으라고 AI가 문제 추천도 해준다죠
저 하노이의 탑 문제 못풀고 필기 떨한거 어떻게 알았어요? ㅋ
'공부 > 코딩' 카테고리의 다른 글
[코테풀이챌린지] 10진수를 2진수로 변환하기 (1) | 2025.01.14 |
---|---|
[프로그래머스] 방문 길이 (0) | 2025.01.06 |
[프로그래머스/연습문제] 행렬의 곱셈 (5) | 2025.01.04 |
[프로그래머스/완전탐색] 모의고사 (4) | 2025.01.03 |
[프로그래머스/월간코드챌린지] 두 개 뽑아서 더하기 (feat.코딩 테스트 합격자 되기 자바편) (4) | 2025.01.03 |