💡 문제
maximum-number-of-alloys (https://leetcode.com/problems/maximum-number-of-alloys/description/)
자세한 문제 설명과 입출력 예는 링크를 참고해주세요.
📝 선행 개념
🤓 문제 풀이
🔨 문제 설명
여러 종류의 금속을 사용하여 합금을 만드는 회사의 소유자입니다. 사용할 수 있는 기계는 k대이며, 각 기계는 합금을 만들기 위해 각 금속 유형의 특정 양을 필요로 합니다.
i번째 기계가 합금을 만들려면, composition[i][j]는 j번째 금속 유형의 단위 수를 필요로 합니다. 초기에는 각 금속 유형에 대해 stock[i]단위의 금속을 가지고 있으며, 금속 유형 i의 구매 비용은 cost[i]코인입니다.
정수 n, k, 예산 budget, 1-인덱스 2차원 배열 composition, 그리고 1-인덱스 배열 stock 및 cost가 주어집니다. 회사가 예산 내에서 최대한 많은 합금을 만드는 것이 목표입니다.
회사가 만들 수 있는 최대 합금 수를 반환합니다.
주어진 문제는 여러 종류의 금속을 사용하여 합금을 만드는 회사의 문제입니다. 회사는 k개의 기계를 가지고 있으며, 각 기계는 특정한 금속 구성으로 합금을 생산합니다. 각 기계는 다음과 같은 조건을 가지고 있습니다:
- 각 기계는 composition[i][j] 단위의 j번째 금속을 필요로 합니다.
- 초기에 각 금속 유형의 stock[i] 단위를 보유하고 있으며, 한 단위의 금속을 구매하는 비용은 cost[i]입니다.
목표는 다음과 같습니다:
- 주어진 예산 내에서 가능한 한 많은 수의 합금을 생산하는 것입니다.
- 모든 합금은 동일한 기계를 사용하여 생산해야 합니다.
🔨 접근 방법
- 각 기계별 생산 가능한 합금 수 계산: 각 기계별로 얼마나 많은 합금을 생산할 수 있는지를 계산합니다. 이는 각 기계가 필요로 하는 금속의 양과 현재 보유한 금속 재고를 기준으로 결정됩니다.
- 예산 내에서 최대 합금 수 계산: 각 기계를 선택했을 때 필요한 총 비용을 계산하고, 주어진 예산 내에서 최대로 생산할 수 있는 합금 수를 계산합니다. 이를 통해 가장 많은 합금을 생산할 수 있는 최적의 기계를 선택합니다.
🔨 문제 풀이 과정
- 각 기계별 생산 가능한 합금 수 계산:
- 각 기계를 순회하면서 해당 기계의 composition을 확인합니다.
- 각 금속에 대해 필요한 양과 보유한 재고를 비교하여 최대로 생산할 수 있는 합금 수를 계산합니다.
- 이 값을 maxAlloysWithThisMachine 변수에 저장합니다.
- 최대 합금 수 계산:
- 각 기계를 선택했을 때 필요한 총 비용을 계산합니다.
- 각 금속의 필요한 양과 비용을 곱하여 총 비용을 계산하고, 이를 totalCost 변수에 저장합니다.
- 주어진 예산 budget 내에서 최대로 생산할 수 있는 합금 수를 계산합니다. 이를 maxPossibleAlloys 변수에 저장합니다.
- 최대 합금 수 업데이트:
- 각 기계를 순회하면서 maxPossibleAlloys 값이 가장 큰 경우를 찾아 maxAlloys 변수에 저장합니다.
- 결과 반환:
- 모든 기계를 확인한 후에 maxAlloys 값을 반환하여 주어진 조건 내에서 최대 합금 수를 구합니다.
🔨 구현코드
import java.util.List;
class Solution {
// 주어진 예산 내에서 최대 합금 개수를 구하는 함수
public int maxNumberOfAlloys(int n, int k, int budget, List<List<Integer>> composition, List<Integer> stock, List<Integer> cost) {
int maxAlloys = 0;// 최대 합금 개수를 저장할 변수
// 각 기계에 대해 최대 합금 개수를 이진 탐색으로 찾음
for (int machine = 0; machine < k; machine++) {
int low = 0; // 최소값 초기화
int high = (int) 1e9; // 10^9으로 high 값을 설정 최대값을 크게 설정 (실제 가능한 최대값 보다 크게 설정)
// 이진 탐색을 이용하여 최대 합금 개수를 찾음
while (low < high) {
int mid = (low + high + 1) / 2; // 중간값 계산
if (canProduceAlloys(n, budget, composition.get(machine), stock, cost, mid)) {
low = mid;// 가능하면 low를 늘려서 더 많은 합금을 만들 수 있는지 확인
} else {
high = mid - 1; // 불가능하면 high를 줄여서 더 적은 합금을 만들도록 함
}
}
// 현재 기계에서 찾은 최대 합금 개수를 최대값과 비교하여 갱신
maxAlloys = Math.max(maxAlloys, low);
}
return maxAlloys; // 최대 합금 개수 반환
}
// 주어진 개수의 합금을 만들 수 있는지 여부를 판단하는 함수
private boolean canProduceAlloys(int n, int budget, List<Integer> comp, List<Integer> stock, List<Integer> cost, int target) {
long totalCost = 0; // 총 비용을 저장할 변수
// 각 금속에 대해 필요한 양과 비용을 계산하여 총 비용을 구함
for (int i = 0; i < n; i++) {
long required = (long) comp.get(i) * target; // 필요한 금속 양
if (required > stock.get(i)) { // 재고보다 많이 필요한 경우
totalCost += (required - stock.get(i)) * cost.get(i); // 추가 구매 비용 계산
if (totalCost > budget) { // 예산을 초과하면 false 반환
return false;
}
}
}
return totalCost <= budget; // 총 비용이 예산 내에 있는 경우 true 반환
}
}
📚 풀이 보완
코드 설명
- canProduceAlloys 함수:
- canProduceAlloys 함수는 주어진 개수의 합금을 만들 수 있는지 여부를 판단합니다.
- comp 리스트는 현재 기계의 금속 조성을 나타내며, stock은 각 금속의 재고, cost는 각 금속의 구매 비용을 나타냅니다.
- target은 만들고자 하는 합금의 개수입니다.
- 필요한 금속의 양을 계산하고, 재고보다 부족한 경우 추가 구매 비용을 계산합니다.
- 총 비용이 예산을 초과하는 경우 false를 반환하고, 그렇지 않으면 true를 반환합니다.
- maxNumberOfAlloys 함수:
- maxNumberOfAlloys 함수는 각 기계별로 최대한 많은 합금을 만들 수 있는지 이진 탐색을 사용하여 찾습니다.
- composition은 각 기계의 금속 조성을 나타내며, stock과 cost는 각각 금속의 재고와 구매 비용을 나타냅니다.
- 각 기계에 대해 이진 탐색을 수행하여 최대 합금 개수를 찾습니다.
- low는 가능한 최대 합금 개수를 찾기 위해 시작하는 값이고, high는 충분히 큰 값을 설정하여 가능한 최대 합금 개수를 탐색합니다.
- 이진 탐색을 통해 각 기계에서 가능한 최대 합금 개수를 찾고, 이 중에서 가장 큰 값을 maxAlloys에 저장하여 반환합니다.
이번 문제는 풀기가 어려웠다 테스트 케이스를 여러개 추가를 하면서 확인을 했다.
내가 실패한 이유는
- canProduce 함수가 모든 기계를 제대로 확인하지 않고, 첫 번째 가능한 기계에서 true를 반환하도록 작성되어 정확한 판단을 하지 못함.
- 이진 탐색의 high 값을 예산으로 설정하여 실제 최대 합금 개수를 제대로 탐색하지 못함.
이후 통과를 할 수 있었던 이유는
- 각 기계별로 최대 합금 개수를 정확히 계산하여 최댓값을 반환함.
- 이진 탐색 범위를 충분히 크게 설정하여 실제 가능한 최대 합금 개수를 탐색함.
📍 Plus+
공간 복잡도
추가적인 데이터 구조를 생성하지 않고 입력으로 주어진 변수들만을 사용하므로, O(1)의 공간 복잡도를 가집니다.
시간복잡도
- totalCost 함수는 주어진 금속 구성과 재고, 비용을 바탕으로 mid 개의 합금을 만들기 위한 총 비용을 계산합니다.
- 금속의 종류를 나타내는 n에 대해 O(n) 시간이 소요됩니다.
- canProduce 함수는 각 기계별로 mid 개의 합금을 만들 수 있는지 확인합니다.
- 기계의 수를 나타내는 k에 대해 O(k * n) 시간이 소요됩니다 (모든 기계와 그에 따른 금속 구성을 확인해야 하므로).
- 따라서 canProduce 함수의 시간 복잡도는 O(k * n)
- maxNumberOfAlloys 함수는 이진 탐색을 사용하여 최대 합금 수를 찾습니다.
- 이진 탐색에서는 low와 high의 값이 각각 budget과 1e9로 초기화되어 있으며, 이진 탐색을 수행할 때마다 반씩 범위를 줄여나가므로 O(log budget)의 시간이 소요됩니다.
- canProduce 함수의 호출은 O(k * log budget) 시간이 소요됩니다.
- 따라서 maxNumberOfAlloys 함수의 시간 복잡도는 O(k * n * log budget)
요약
- 공간 복잡도 : O(1)
- 시간 복잡도 : O(k * n * log budget)
'알고리즘 & 자료구조 > 코딩테스트 준비' 카테고리의 다른 글
[리트코드][JAVA] 556. next-greater-element-iii (더 큰 요소 III) (1) | 2024.06.18 |
---|---|
[리트코드][JAVA] 2145. count-the-hidden-sequences(숨겨진 시퀀스 계산) (1) | 2024.06.16 |
[리트코드][JAVA] 275. h-index-ii (H-지수 II) (1) | 2024.06.16 |
[리트코드][JAVA] 1971. Find-if-path-exists-in-graph(그래프에 경로가 존재하는지 찾기) (0) | 2024.06.16 |
[프로그래머스][JAVA] 49190. 방의 개수 (1) | 2024.06.16 |