Eat Study Love

먹고 공부하고 사랑하라

Coding_Practice

Combination Sum II[M,Array,Backtracking]

eatplaylove 2024. 8. 13. 21:58

https://leetcode.com/problems/combination-sum-ii/?envType=daily-question&envId=2024-08-13

Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sum to target.

Each number in candidates may only be used once in the combination.

Note: The solution set must not contain duplicate combinations.

 

Example 1:

Input: candidates = [10,1,2,7,6,1,5], target = 8
Output: 
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

Example 2:

Input: candidates = [2,5,2,1,2], target = 5
Output: 
[
[1,2,2],
[5]
]

 

Constraints:

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

1. Python

시험에 나왔던 문제다.

개인적으로 너무 어렵다 진짜..

 

def combinationSum2(candidates,target):
    candidates.sort()
    results = []
    stack = [(0, 0, [])]  # (start_index, current_sum, current_path)
    while stack:
        start, curr_sum, path = stack.pop()
        if curr_sum == target:
            results.append(path)
            continue
        for i in range(start, len(candidates)):
            # 중복 제거
            if i > start and candidates[i] == candidates[i - 1]:
                continue
            # 현재 선택한 수가 목표값을 초과하면 탐색 종료
            if curr_sum + candidates[i] > target:
                break
            # 다음 상태를 스택에 추가
            stack.append((i + 1, curr_sum + candidates[i], path + [candidates[i]]))
        print(stack)
        print(results)
    return results

# 테스트 코드
numbers =[10,1,2,7,6,1,5]
# [1,1,2,5,6,7,10]
target = 8
print(combinationSum2(numbers, target))

 

파이썬으로도 쩔쩔 매는데, 이거 C / C++로는 엄두가 나지도 않는다..

 

while문을 recursive하게 쓰면 아래와 같다.

 

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        def backtrack(start,target,path):
            if target == 0 :
                ans.append(path)
                return
            if target < 0 :
                return
            for i in range(start,len(candidates)):
                #for duplicate
                if i > start and candidates[i] == candidates[i-1]:
                    continue
                backtrack(i+1,target-candidates[i],path+[candidates[i]])
        candidates.sort()
        ans = []
        backtrack(0,target,[])
        return ans

 

2. C

# C
#include <stdio.h>
#include <stdlib.h>

void backtrack(int* candidates, int candidatesSize, int target, int* path, int pathSize, int start, int** ans, int* ansSize, int** colSizes) {
    if (target == 0) {
        ans[*ansSize] = (int*)malloc(sizeof(int) * pathSize);
        for (int i = 0; i < pathSize; i++) {
            ans[*ansSize][i] = path[i];
        }
        (*colSizes)[*ansSize] = pathSize;
        (*ansSize)++;
        return;
    }
    
    for (int i = start; i < candidatesSize; i++) {
        if (i > start && candidates[i] == candidates[i - 1]) continue;
        if (target - candidates[i] < 0) break;
        
        path[pathSize] = candidates[i];
        backtrack(candidates, candidatesSize, target - candidates[i], path, pathSize + 1, i + 1, ans, ansSize, colSizes);
    }
}

int compare(const void* a, const void* b) {
    return (*(int*)a - *(int*)b);
}

int** combinationSum2(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes) {
    qsort(candidates, candidatesSize, sizeof(int), compare);
    int** ans = (int**)malloc(1000 * sizeof(int*));
    int* path = (int*)malloc(candidatesSize * sizeof(int));
    *returnColumnSizes = (int*)malloc(1000 * sizeof(int));
    *returnSize = 0;
    
    backtrack(candidates, candidatesSize, target, path, 0, 0, ans, returnSize, returnColumnSizes);
    
    free(path);
    return ans;
}

int main() {
    int candidates[] = {10, 1, 2, 7, 6, 1, 5};
    int candidatesSize = sizeof(candidates) / sizeof(candidates[0]);
    int target = 8;
    int returnSize;
    int* returnColumnSizes;
    
    int** result = combinationSum2(candidates, candidatesSize, target, &returnSize, &returnColumnSizes);
    
    for (int i = 0; i < returnSize; i++) {
        printf("[");
        for (int j = 0; j < returnColumnSizes[i]; j++) {
            printf("%d%s", result[i][j], j == returnColumnSizes[i] - 1 ? "" : ", ");
        }
        printf("]\n");
        free(result[i]);
    }
    
    free(result);
    free(returnColumnSizes);
    
    return 0;
}

 

 

3. C++

# C++
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void backtrack(vector<int>& candidates, int target, vector<int>& path, int start, vector<vector<int>>& ans) {
    if (target == 0) {
        ans.push_back(path);
        return;
    }
    
    for (int i = start; i < candidates.size(); i++) {
        if (i > start && candidates[i] == candidates[i - 1]) continue;
        if (target - candidates[i] < 0) break;
        
        path.push_back(candidates[i]);
        backtrack(candidates, target - candidates[i], path, i + 1, ans);
        path.pop_back();
    }
}

vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
    sort(candidates.begin(), candidates.end());
    vector<vector<int>> ans;
    vector<int> path;
    backtrack(candidates, target, path, 0, ans);
    return ans;
}

int main() {
    vector<int> candidates = {10, 1, 2, 7, 6, 1, 5};
    int target = 8;
    vector<vector<int>> result = combinationSum2(candidates, target);
    
    for (const auto& comb : result) {
        cout << "[";
        for (int i = 0; i < comb.size(); i++) {
            cout << comb[i] << (i == comb.size() - 1 ? "" : ", ");
        }
        cout << "]\n";
    }
    
    return 0;
}

 

쉽지 않다..