编程语言
首页 > 编程语言> > 【数据结构与算法】之深入解析“组合总和III”的求解思路与算法示例

【数据结构与算法】之深入解析“组合总和III”的求解思路与算法示例

作者:互联网

一、题目要求

输入: k = 3, n = 7
输出: [[1,2,4]]
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]

二、求解算法

① 回溯+剪枝

在这里插入图片描述

vector<vector<int>> result; // 存放结果集
vector<int> path; 			// 符合条件的结果
vector<vector<int>> result;
vector<int> path;
void backtracking(int targetSum, int k, int sum, int startIndex)
if (path.size() == k) {
    if (sum == targetSum) result.push_back(path);
    return; // 如果path.size() == k 但sum != targetSum 直接返回
}

在这里插入图片描述

for (int i = startIndex; i <= 9; i++) {
    sum += i;
    path.push_back(i);
    backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
    sum -= i; 		 // 回溯
    path.pop_back(); // 回溯
}
class Solution {
private:
    vector<vector<int>> result; // 存放结果集
    vector<int> path; // 符合条件的结果
    // targetSum:目标和,也就是题目中的n。
    // k:题目中要求k个数的集合。
    // sum:已经收集的元素的总和,也就是path里元素的总和。
    // startIndex:下一层for循环搜索的起始位置。
    void backtracking(int targetSum, int k, int sum, int startIndex) {
        if (path.size() == k) {
            if (sum == targetSum) result.push_back(path);
            return; // 如果path.size() == k 但sum != targetSum 直接返回
        }
        for (int i = startIndex; i <= 9; i++) {
            sum += i; 		   // 处理
            path.push_back(i); // 处理
            backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
            sum -= i; 		 // 回溯
            path.pop_back(); // 回溯
        }
    }

public:
    vector<vector<int>> combinationSum3(int k, int n) {
        result.clear(); // 可以不加
        path.clear();   // 可以不加
        backtracking(n, k, 0, 1);
        return result;
    }
};
int *path;
int pathTop;
int **result;
int resultTop;

void backTrack(int k,int n,int sum ,int startIndex){
    if(pathTop==k){
        if(n == sum){
            int *temp = malloc(sizeof(int)*k);
            for(int i =0;i<k;i++){
                temp[i] = path[i];
            }
            result[resultTop++] = temp;
        }
        return ;
    }
    for(int j=startIndex;j<=9-(k-pathTop)+1;j++){
        sum = sum + j;
        path[pathTop++] = j;
        backTrack(k,n,sum,j+1);
        sum = sum -j;
        pathTop--;
    }
}
int** combinationSum3(int k, int n, int* returnSize, int** returnColumnSizes){
    pathTop = resultTop = 0;
    path = malloc(sizeof(int) *k);
    result = malloc(sizeof(int*) *100);
    backTrack(k,n,0,1);
    *returnSize = resultTop;
    *returnColumnSizes = malloc(sizeof(int*) * resultTop);
    for(int i=0 ; i<resultTop ; i++){
        (*returnColumnSizes)[i] = k;
    }
    return result;
}

在这里插入图片描述

if (sum > targetSum) { // 剪枝操作
    return;
}
class Solution {
private:
    vector<vector<int>> result; // 存放结果集
    vector<int> path; // 符合条件的结果
    void backtracking(int targetSum, int k, int sum, int startIndex) {
        if (sum > targetSum) { // 剪枝操作
            return; // 如果path.size() == k 但sum != targetSum 直接返回
        }
        if (path.size() == k) {
            if (sum == targetSum) result.push_back(path);
            return;
        }
        for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) { // 剪枝
            sum += i; // 处理
            path.push_back(i); // 处理
            backtracking(targetSum, k, sum, i + 1); // 注意i+1调整startIndex
            sum -= i; // 回溯
            path.pop_back(); // 回溯
        }
    }

public:
    vector<vector<int>> combinationSum3(int k, int n) {
        result.clear(); // 可以不加
        path.clear();   // 可以不加
        backtracking(n, k, 0, 1);
        return result;
    }
};
class Solution {
	List<List<Integer>> result = new ArrayList<>();
	LinkedList<Integer> path = new LinkedList<>();

	public List<List<Integer>> combinationSum3(int k, int n) {
		backTracking(n, k, 1, 0);
		return result;
	}

	private void backTracking(int targetSum, int k, int startIndex, int sum) {
		// 减枝
		if (sum > targetSum) {
			return;
		}

		if (path.size() == k) {
			if (sum == targetSum) result.add(new ArrayList<>(path));
			return;
		}
		
		// 减枝 9 - (k - path.size()) + 1
		for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {
			path.add(i);
			sum += i;
			backTracking(targetSum, k, i + 1, sum);
			// 回溯
			path.removeLast();
			// 回溯
			sum -= i;
		}
	}
}

② 二进制(子集)枚举

class Solution {
public:
    vector<int> temp;
    vector<vector<int>> ans;

    bool check(int mask, int k, int n) {
        temp.clear();
        for (int i = 0; i < 9; ++i) {
            if ((1 << i) & mask) {
                temp.push_back(i + 1);
            }
        }
        return temp.size() == k && accumulate(temp.begin(), temp.end(), 0) == n; 
    }

    vector<vector<int>> combinationSum3(int k, int n) {
        for (int mask = 0; mask < (1 << 9); ++mask) {
            if (check(mask, k, n)) {
                ans.emplace_back(temp);
            }
        }
        return ans;
    }
};
class Solution {
    List<Integer> temp = new ArrayList<Integer>();
    List<List<Integer>> ans = new ArrayList<List<Integer>>();

    public List<List<Integer>> combinationSum3(int k, int n) {
        for (int mask = 0; mask < (1 << 9); ++mask) {
            if (check(mask, k, n)) {
                ans.add(new ArrayList<Integer>(temp));
            }
        }
        return ans;
    }

    public boolean check(int mask, int k, int n) {
        temp.clear();
        for (int i = 0; i < 9; ++i) {
            if (((1 << i) & mask) != 0) {
                temp.add(i + 1);
            }
        }
        if (temp.size() != k) {
            return false;
        }
        int sum = 0;
        for (int num : temp) {
            sum += num;
        }
        return sum == n;
    }
}

标签:return,示例,int,sum,算法,targetSum,path,III,result
来源: https://blog.csdn.net/Forever_wj/article/details/122410145