문제설명
입력 & 출력
나의 풀이
이번 문제는 각 작업이 완료되기까지 필요한 일수를 계산하고, 각 배포마다 몇 개의 기능이 배포되는지를 구하는 문제입니다.
각 기능은 100%가 되어야 배포가 되며 각 기능마다 100%까지 필요한 일수가 다르기 때문에 이 점을 고려해야 합니다.
입출력 예 #1을 예로 들어 설명하자면 다음과 같습니다.
- 첫 번째 기능
- 현재 진행 상황: 93%
- 속도: 1%
- 남은 작업량: 100 - 93 = 7%
- 걸리는 일 수: 7 / 1 = 7일
- 두 번째 기능
- 현재 진행 상황: 30%
- 속도: 30%
- 남은 작업량: 100 - 30 = 70%
- 걸리는 일 수: 70 / 30 = 2.333... (올림 하여 3일)
- 세 번째 기능
- 현재 진행 상황: 55%
- 속도: 5%
- 남은 작업량: 100 - 55 = 45%
- 걸리는 일 수: 45 / 5 = 9일
따라서 각 기능이 완료되는 날짜는 다음과 같습니다:
- 첫 번째 기능: 7일
- 두 번째 기능: 3일
- 세 번째 기능: 9일
이 점을 고려하여 코드를 작성해야 합니다.
저는 큐에 넣을 때 맨 앞의 값과 비교하여, 현재 작업이 앞 작업보다 더 오래 걸린다면 기다려야 하며, 작업이 앞 작업보다 더 빨리 끝난다면 앞 작업을 배포할 수 있는 조건이라는 것을 판단했습니다.
import java.util.*;
class Solution {
public int[] solution(int[] progresses, int[] speeds) {
Queue<Integer> queue = new LinkedList<>();
List<Integer> result = new ArrayList<>();
for (int i = 0; i < progresses.length; i++) {
int days = (int)Math.ceil((100.0 - progresses[i]) / speeds[i]);
if (!queue.isEmpty() && queue.peek() < days) { // 넣을 값이 크면 큐 비우기
result.add(queue.size());
queue.clear();
}
queue.offer(days);
}
result.add(queue.size());
// List를 배열로 변환
int[] answer = new int[result.size()];
for (int i = 0; i < result.size(); i++) {
answer[i] = result.get(i);
}
return answer;
}
}
풀이를 설명하자면 먼저 Queue와 ArrayList를 선언해 줍니다. ArrayList를 선언하는 이유는 배포를 하는 작업의 개수를 저장하기 위함입니다.
그리고 for문을 사용하여 prgresses 배열과 sppeds에 접근을 해줍니다.
이제 작업이 완료될 수 있는 일수 days를 구해야 하는 데 Math.ceil() 메서드를 사용하여 올림을 해주고, 필요한 일수를 구해줍니다.
이때 Java에서 정수 나눗셈의 결과는 정수이기 때문에, 만약 (100 - progresses [i]) / speeds [i]와 같이 정수로 계산하면 정확한 일수를 구할 수 없을 수 있습니다.
예를 들어, (93 - 30) / 30을 계산하면 결과는 2가 되지만, 실제로는 2.1일이 필요합니다.
따라서 (100.0 - progresses [i]) / speeds [i]에서 100.0과 같이 소수점이 포함된 실수로 계산하면 실수 나눗셈이 이루어지게 됩니다.
이렇게 하면 결과는 소수점 이하까지 정확하게 계산할 수 있습니다. 예를 들어, (100.0 - 93) / 30을 계산하면 결과는 약 0.2333이 되어서 올림 한 경우 1일이 필요함을 정확히 구할 수 있습니다.
그리고 각 필요한 일 수를 큐에 넣어주는 작업을 해야 합니다. 이때 offer() 메서드를 사용하여 큐에 데이터를 넣어줍니다.
if문에서는 에러방지를 위하여 isEmpty() 메서드를 사용하여 큐가 비어있는지 확인하고, 현재 작업의 days가 큐의 맨 앞 요소 peek() 보다 크다면 큐에 있는 작업들은 배포를 해도 됩니다.
따라서 조건문을 위와 같이 지정해 주고, (큐의 size() == 배포할 수 있는 작업의 수)를 list에 추가해 줍니다.
그리고 큐를 clear() 메서드를 사용하여 비워줍니다. 큐를 비워주는 이유는 다음 배포를 위해 새로운 작업들을 다시 큐에 넣어 관리하기 위함입니다.
그리고 큐에 남아있는 마지막 작업을 list에 추가를 해줍니다.
그리고 최종 반환은 배열이기 때문에 List를 배열로 변환하는 작업이 필요합니다. size() 메서드를 사용하여 배열의 크기를 지정해 주고, answer배열에 배포 작업 수를 넣어줍니다.
refactoring ✅
import java.util.*;
class Solution {
public int[] solution(int[] progresses, int[] speeds) {
Queue<Integer> queue = new LinkedList<>();
ArrayList<Integer> list = new ArrayList<>();
int[] answer = {};
for(int i = 0 ; i < progresses.length ; i++){
int days = (int)Math.ceil((100.0 - progresses[i]) / speeds[i]);
if(!queue.isEmpty() && queue.peek() < days){
list.add(queue.size());
queue.clear();
}
queue.offer(days);
}
list.add(queue.size());
return list.stream().mapToInt(i -> i).toArray();
}
}
전체적인 코드는 "나의 풀이"와 동일합니다. 차이점은 return문에서 stream API를 사용한 것입니다.
- list.stream()
- 리스트(list)를 스트림으로 변환합니다.
- 스트림은 데이터의 연속적인 흐름을 나타내며, 스트림을 사용하여 데이터를 필터링, 매핑, 정렬 등 다양한 연산을 수행할 수 있습니다.
- mapToInt(i -> i)
- mapToInt() 메서드는 각 요소를 특정 형식으로 매핑하는 스트림 연산입니다.
- 여기서는 각 요소(i)를 그대로 반환하도록 하여 int 형태로 매핑합니다.
- 즉 i -> i는 입력값(i)을 그대로 출력값으로 반환하는 간단한 람다 표현식입니다.
- toArray()
- toArray() 메서드는 스트림의 요소들을 배열로 변환하여 반환합니다.
참고 ❗
'Coding Test > 프로그래머스' 카테고리의 다른 글
[프로그래머스] Lv.1 K번째 수 (copyOfRange(), Java) (1) | 2024.06.16 |
---|---|
[프로그래머스] Lv.2 프로세스 (PriorityQueue, poll(), offer() ,Java) (1) | 2024.06.16 |
[프로그래머스] Lv.2 의상 (HashMap, getOrDefault, Java) (0) | 2024.06.15 |
[프로그래머스] Lv.2 튜플 (LinkedHashSet, replaceAll, substring, Java) (0) | 2024.06.15 |
[프로그래머스] Lv.1 다트게임 (StringBuilder, isDigit(), isLetter(),Java) (1) | 2024.06.14 |