算法leetcode剑指 Offer II 081. 允许重复选择元素的组合(多语言实现)

Posted 二当家的白帽子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法leetcode剑指 Offer II 081. 允许重复选择元素的组合(多语言实现)相关的知识,希望对你有一定的参考价值。


文章目录


剑指 Offer II 081. 允许重复选择元素的组合:

给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。

candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的唯一组合数少于 150 个。

样例 1:

输入: 
	candidates = [2,3,6,7], target = 7
	
输出: 
	[[7],[2,2,3]]

样例 2:

输入: 
	candidates = [2,3,5], target = 8
	
输出: 
	[[2,2,2,2],[2,3,3],[3,5]]

样例 3:

输入: 
	candidates = [2], target = 1
	
输出: 
	[]

样例 4:

输入: 
	candidates = [1], target = 1
	
输出: 
	[[1]]

样例 5:

输入: 
	candidates = [1], target = 2
	
输出: 
	[[1,1]]

提示:

  • 1 <= candidates.length <= 30
  • 1 <= candidates[i] <= 200
  • candidate 中的每个元素都是独一无二的。
  • 1 <= target <= 500

分析

  • 面对这道算法题目,二当家的陷入了沉思。
  • 最直观的方式就是递归套娃大法了。
  • 每个数字都可以选择,或者不选择。
  • 需要注意的就是每个数字都是可以重复选择的,由于是组合,所以我们就遍历数组,按顺序选择(选择当前数字或者跳过当前数字),直到和大于等于目标值。

题解

rust

impl Solution 
    pub fn combination_sum(candidates: Vec<i32>, target: i32) -> Vec<Vec<i32>> 
        fn dfs(candidates: &Vec<i32>, target: i32, idx: usize, row: &mut Vec<i32>, ans: &mut Vec<Vec<i32>>) 
            if target == 0 
                // 符合条件的一个组合
                ans.push(row.clone());
                return;
            
            if idx >= candidates.len() 
                // 尝试到底,开始回溯
                return;
            
            // 跳过当前下标数字
            dfs(candidates, target, idx + 1, row, ans);
            // 选择当前下标数字
            if target - candidates[idx] >= 0 
                row.push(candidates[idx]);
                dfs(candidates, target - candidates[idx], idx, row, ans);
                row.pop();
            
        

        let mut ans = Vec::new();
        dfs(&candidates, target, 0, &mut Vec::new(), &mut ans);
        ans
    


go

func combinationSum(candidates []int, target int) [][]int 
    var ans [][]int

	var dfs func(int, int, []int, int)
	dfs = func(target int, idx int, row []int, rowSize int) 
		if target == 0 
			// 符合条件的一个组合
			ans = append(ans, append([]int, row[0:rowSize]...))
			return
		
		if idx >= len(candidates) 
			// 尝试到底,开始回溯
			return
		
		// 跳过当前下标数字
		dfs(target, idx+1, row, rowSize)
		// 选择当前下标数字
		if target-candidates[idx] >= 0 
			row[rowSize] = candidates[idx]
			dfs(target-candidates[idx], idx, row, rowSize+1)
		
	

	dfs(target, 0, make([]int, target), 0)

	return ans


typescript

function combinationSum(candidates: number[], target: number): number[][] 
    function dfs(target: number, idx: number, row: number[]) 
		if (target == 0) 
			// 符合条件的一个组合
			ans.push([...row]);
			return;
		
		if (idx >= candidates.length) 
			// 尝试到底,开始回溯
			return;
		
		// 跳过当前下标数字
		dfs(target, idx + 1, row);
		// 选择当前下标数字
		if (target - candidates[idx] >= 0) 
			row.push(candidates[idx]);
			dfs(target - candidates[idx], idx, row);
			row.pop();
		
	

	const ans = [];
	dfs(target, 0, []);
	return ans;
;

python

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        ans = []

        def dfs(target: int, idx: int, row: List[int]):
            if target == 0:
                # 符合条件的一个组合
                ans.append(row.copy())
                return
            if idx >= len(candidates):
                # 尝试到底,开始回溯
                return
            # 跳过当前下标数字
            dfs(target, idx + 1, row)
            # 选择当前下标数字
            if target - candidates[idx] >= 0:
                row.append(candidates[idx])
                dfs(target - candidates[idx], idx, row)
                row.pop()

        dfs(target, 0, [])
        return ans


c

void dfs(int *candidates, int candidatesSize, int target, int idx, int *row, int rowSize, int **ans, int *returnSize,
         int **returnColumnSizes) 
    if (target == 0) 
        // 符合条件的一个组合
        ans[*returnSize] = (int *) malloc(sizeof(int) * rowSize);
        memcpy(ans[*returnSize], row, sizeof(int) * rowSize);
        (*returnColumnSizes)[*returnSize] = rowSize;
        ++(*returnSize);
        return;
    
    if (idx >= candidatesSize) 
        // 尝试到底,开始回溯
        return;
    
    // 跳过当前下标数字
    dfs(candidates, candidatesSize, target, idx + 1, row, rowSize, ans, returnSize, returnColumnSizes);
    // 选择当前下标数字
    if (target - candidates[idx] >= 0) 
        row[rowSize] = candidates[idx];
        dfs(candidates, candidatesSize, target - candidates[idx], idx, row, rowSize + 1, ans, returnSize,
            returnColumnSizes);
    


/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int **combinationSum(int *candidates, int candidatesSize, int target, int *returnSize, int **returnColumnSizes) 
    *returnSize = 0;
    *returnColumnSizes = (int *) malloc(sizeof(int) * 150);
    int **ans = (int **) malloc(sizeof(int *) * 150);
    int row[target];
    dfs(candidates, candidatesSize, target, 0, row, 0, ans, returnSize, returnColumnSizes);
    return ans;


c++

class Solution 
private:
    void dfs(vector<int>& candidates, int target, int idx, vector<int>& row, vector<vector<int>>& ans) 
        if (target == 0) 
            // 符合条件的一个组合
            ans.emplace_back(row);
            return;
        
        if (idx >= candidates.size()) 
            // 尝试到底,开始回溯
            return;
        
        // 跳过当前下标数字
        dfs(candidates, target, idx + 1, row, ans);
        // 选择当前下标数字
        if (target - candidates[idx] >= 0) 
            row.emplace_back(candidates[idx]);
            dfs(candidates, target - candidates[idx], idx, row, ans);
            row.pop_back();
        
    
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) 
        vector<vector<int>> ans;
        vector<int> row;
        dfs(candidates, target, 0, row, ans);
        return ans;
    
;

java

class Solution 
    public List<List<Integer>> combinationSum(int[] candidates, int target) 
        List<List<Integer>> ans = new ArrayList<>();
        this.dfs(candidates, target, 0, new LinkedList<>(), ans);
        return ans;
    

    private void dfs(int[] candidates, int target, int idx, Deque<Integer> row, List<List<Integer>> ans) 
        if (target == 0) 
            // 符合条件的一个组合
            ans.add(new ArrayList<>(row));
            return;
        
        if (idx >= candidates.length) 
            // 尝试到底,开始回溯
            return;
        
        // 跳过当前下标数字
        this.dfs(candidates, target, idx + 1, row, ans);
        // 选择当前下标数字
        if (target - candidates[idx] >= 0) 
            row.addLast(candidates[idx]);
            this.dfs(candidates, target - candidates[idx], idx, row, ans);
            row.pollLast();
        
    


原题传送门:https://leetcode.cn/problems/Ygoe9J/submissions/


非常感谢你阅读本文~
欢迎【点赞】【收藏】【评论】~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://le-yi.blog.csdn.net/ 博客原创~


以上是关于算法leetcode剑指 Offer II 081. 允许重复选择元素的组合(多语言实现)的主要内容,如果未能解决你的问题,请参考以下文章

算法leetcode剑指 Offer 56 - II. 数组中数字出现的次数 II(多语言实现)

算法leetcode剑指 Offer 56 - II. 数组中数字出现的次数 II(多语言实现)

算法leetcode剑指 Offer II 041. 滑动窗口的平均值(rust重拳出击)

算法leetcode剑指 Offer II 041. 滑动窗口的平均值(rust重拳出击)

LeetCode(剑指 Offer)- II. 剪绳子 II

LeetCode(剑指 Offer)- II. 剪绳子 II