Skip to content

[638] Shopping Offers#649

Merged
dlek-user merged 1 commit intomainfrom
dlek-user-570
Feb 18, 2026
Merged

[638] Shopping Offers#649
dlek-user merged 1 commit intomainfrom
dlek-user-570

Conversation

@dlek-user
Copy link
Copy Markdown
Collaborator

[638] Shopping Offers

문제 설명

In LeetCode Store, there are n items to sell. Each item has a price. However, there are some special offers, and a special offer consists of one or more different kinds of items with a sale price.

You are given an integer array price where price[i] is the price of the ith item, and an integer array needs where needs[i] is the number of pieces of the ith item you want to buy.

You are also given an array special where special[i] is of size n + 1 where special[i][j] is the number of pieces of the jth item in the ith offer and special[i][n] (i.e., the last integer in the array) is the price of the ith offer.

Return the lowest price you have to pay for exactly certain items as given, where you could make optimal use of the special offers. You are not allowed to buy more items than you want, even if that would lower the overall price. You could use any of the special offers as many times as you want.

Example 1:

Input: price = [2,5], special = [[3,0,5],[1,2,10]], needs = [3,2]
Output: 14
Explanation: There are two kinds of items, A and B. Their prices are $2 and $5 respectively.
In special offer 1, you can pay $5 for 3A and 0B
In special offer 2, you can pay $10 for 1A and 2B.
You need to buy 3A and 2B, so you may pay $10 for 1A and 2B (special offer #2), and $4 for 2A.

Example 2:

Input: price = [2,3,4], special = [[1,1,0,4],[2,2,1,9]], needs = [1,2,1]
Output: 11
Explanation: The price of A is $2, and $3 for B, $4 for C.
You may pay $4 for 1A and 1B, and $9 for 2A ,2B and 1C.
You need to buy 1A ,2B and 1C, so you may pay $4 for 1A and 1B (special offer #1), and $3 for 1B, $4 for 1C.
You cannot add more items, though only $9 for 2A ,2B and 1C.

코드 설명

class Solution {
    private Map<String, Integer> memo = new HashMap<>();

    public int shoppingOffers(
            List<Integer> price,
            List<List<Integer>> special,
            List<Integer> needs
    ) {
        return dfs(price, special, needs);
    }

    private int dfs(
            List<Integer> price,
            List<List<Integer>> special,
            List<Integer> needs
    ) {

        String key = needs.toString();

        if (memo.containsKey(key)) {
            return memo.get(key);
        }

        int minCost = 0;
        for (int i = 0; i < needs.size(); i++) {
            minCost += needs.get(i) * price.get(i);
        }

        for (List<Integer> offer : special) {

            List<Integer> newNeeds = new ArrayList<>();
            boolean valid = true;

            for (int i = 0; i < needs.size(); i++) {

                int remain = needs.get(i) - offer.get(i);

                if (remain < 0) {
                    valid = false;
                    break;
                }

                newNeeds.add(remain);
            }

            if (valid) {

                int offerPrice = offer.get(offer.size() - 1);

                int totalCost = offerPrice + dfs(price, special, newNeeds);

                minCost = Math.min(minCost, totalCost);
            }
        }

        memo.put(key, minCost);

        return minCost;
    }
}

private Map<String, Integer> memo = new HashMap<>();

같은 needs 상태를 여러 번 계산하면 시간 초과
그래서 이미 계산된 상태를 저장

public int shoppingOffers

LeetCode에서 호출하는 진입점
내부적으로 dfs 호출

private int dfs

현재 needs 상태에서 만들 수 있는 최소 비용을 반환

String key = needs.toString();

상태 문자열 변환

if (memo.containsKey(key)) {
    return memo.get(key);
}

중복 계산 방지
→ 시간복잡도 대폭 감소

int minCost = 0;
for (int i = 0; i < needs.size(); i++) {
    minCost += needs.get(i) * price.get(i);
}

special 안 쓰고 그냥 다 정가로 사는 경우

for (List<Integer> offer : special)

각 special offer 시도

int remain = needs.get(i) - offer.get(i);
if (remain < 0)

offer가 요구 수량보다 많으면
불가능

int totalCost = offerPrice + dfs(price, special, newNeeds);

현재 offer 가격
남은 상품 최소 비용

minCost = Math.min(minCost, totalCost);

최소값 갱신

memo.put(key, minCost);

이 상태는 다시 계산하지 않도록 저장

[638] Shopping Offers
@dlek-user dlek-user added the coding test 코딩테스트 라벨 label Feb 17, 2026
@dlek-user dlek-user merged commit 0b617c1 into main Feb 18, 2026
@dlek-user dlek-user deleted the dlek-user-570 branch February 18, 2026 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

coding test 코딩테스트 라벨

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant