首页 > 试题广场 >

加起来和为目标值的组合(三)

[编程题]加起来和为目标值的组合(三)
  • 热度指数:1796 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
找出所有相加之和是 n 的 k 个数的组合。组合中只含有 1~9的正整数,且保证每种组合中不含有相同的数字。
保证一定有解。结果按字典序升序输出。


示例1

输入

3,7

输出

[[1,2,4]]
示例2

输入

2,3

输出

[[1,2]]
示例3

输入

2,5

输出

[[1,4],[2,3]]
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param k int整型 
     * @param n int整型 
     * @return int整型vector<vector<>>
     */
    vector<vector<int>> res;
    vector<int>path;
    void backtracking(int targetsum,int k,int sum,int startindex){
        if(sum>targetsum)return ;
        if(path.size()==k){
            if(sum==targetsum){
                res.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);
            sum-=i;
            path.pop_back();
        }
    }
    vector<vector<int> > combination(int k, int n) {
        // write code here
        res.clear();
        path.clear();
        backtracking(n,k, 0,1);
        return res;
    }
};

发表于 2022-03-16 13:47:16 回复(0)
为了按字典序升序输出结果,那么我们给候选集的时候就给个有序的,然后从左往右尝试取数凑目标值,而凑数采用经典的回溯算法就好。
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param k int整型 
     * @param n int整型 
     * @return int整型二维数组
     */
    ArrayList<ArrayList<Integer>> results = new ArrayList<>();
    int[] candicates = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
    public int[][] combination (int k, int n) {
        // write code here
        boolean[] used = new boolean[9];
        dfs(n, k, 0, used, new ArrayList<>());
        int[][] res = new int[results.size()][];
        for(int i = 0; i < res.length; i++){
            res[i] = new int[results.get(i).size()];
            for(int j = 0; j < results.get(i).size(); j++){
                res[i][j] = results.get(i).get(j);
            }
        }
        return res;
    }
    
    private void dfs(int rest, int k, int depth, boolean[] used, ArrayList<Integer> path) {
        if(rest < 0){
            return;     // 凑过头了,本次组合无效
        }
        if(path.size() == k){
            // 够k个数且凑足目标值了就添加答案
            if(rest == 0){
                results.add(new ArrayList<>(path));
            }
        }else{
            for(int i = depth; i < candicates.length; i++){
                if(used[i]) continue;
                used[i] = true;
                path.add(candicates[i]);
                dfs(rest - candicates[i], k, i + 1, used, path);
                // 回溯
                used[i] = false;
                path.remove(path.size() - 1);
            }
        }
    }
}

发表于 2021-12-17 11:54:14 回复(2)
class Solution {
  public:
     vector<vector<int>> res;
    vector<int> path;
    void dfs(int k, int n, int cur_sum, int index) {
        if (path.size() == k && cur_sum == n) {
            res.push_back(path);
            return;
        }
        for (int i = index; i <= 9 ; i++) {
            path.push_back(i);
            cur_sum += i;
            dfs(k, n, cur_sum, i + 1);
            cur_sum -= i;
            path.pop_back();
        }
    }
    vector<vector<int> > combination(int k, int n) {
        dfs(k, n, 0, 1);
        return res;
    }
};

发表于 2024-04-20 12:08:36 回复(0)
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param k int整型 
# @param n int整型 
# @return int整型二维数组
#
class Solution:
    def combination(self , k: int, n: int) -> List[List[int]]:
        # write code here
        res = []
        self.traverse([], k, n, res)

        return res

    def traverse(self, tmp, k, target, res):
        if k == len(tmp) and target == 0:
            res.append(tmp.copy())
            return

        if len(tmp) >= k:
            return

        start = 1
        if len(tmp) != 0:
            start = tmp[-1] + 1
        for i in range(start, 10):
            if i in tmp:
                continue

            if i >target:
                break
            
            tmp.append(i)
            self.traverse(tmp, k, target-i, res)
            tmp.pop()

发表于 2024-04-14 21:52:06 回复(0)

回溯+剪枝。超过K个数的结果直接丢弃

import java.util.*;
public class Solution {
    List<List<Integer>> res;
    public int[][] combination (int k, int n) {
        int nums[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        res = new ArrayList<>();
        func(k, n , new ArrayList<Integer> (), nums, 0, 0);
        int[][] r = new int[res.size()][k];
        res.sort(new Comparator<List<Integer>> () {
            public int compare(List<Integer> list1, List<Integer> list2) {
                for(int i = 0; i < list1.size(); ++i) {
                    if(list1.get(i) != list2.get(i)) {
                        return list1.get(i) - list2.get(i);
                    }
                }
                return 0;
            }
        });
        for(int i = 0; i < res.size(); ++i) {
            if(res.get(i).size() != k) continue;
            for(int j = 0; j < res.get(i).size(); ++j) {
                r[i][j] = res.get(i).get(j);
            }
        }
        return r;
    }
    public void func(int k, int n, ArrayList<Integer> list, int[] nums, int cur, int index) {
        if(list.size() > k) return;
        if(cur == n) {
            if(list.size() == k)
                res.add(new ArrayList<>(list));
            return;
        } else if(cur > n || index >= 9) return;
        func(k, n, list, nums, cur, index + 1);
        list.add(nums[index]);
        func(k, n, list, nums, cur + nums[index], index + 1);
        list.remove(list.size() - 1);
    }
}
发表于 2023-04-19 11:19:35 回复(0)

function combination( k , n ) {
// write code here
const res = []
const fn = (i, path) => {
path.push(i)
let sum = path.reduce((s, val) => s += val, 0)
if (sum > n) {
return
}
if (path.length == k && sum == n) {
res.push([...path])
return
}

    for (let j = i + 1; j < n; j++) {
        fn(j, path)
        path.pop()
    }
}
for (let i = 1; i < n; i++) {
    fn(i, [])
}
return res

}

发表于 2023-04-04 10:19:13 回复(0)
package main
import _"fmt"

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param k int整型 
 * @param n int整型 
 * @return int整型二维数组
*/
func combination( k int ,  n int ) [][]int {
    ans:=[][]int{}
    var back_tracking func([]int,int,int)
    back_tracking=func(path []int,sum int,idx int){
        if sum>=n{
            if len(path)==k&&sum==n{
                tmp:=make([]int,len(path))
                copy(tmp,path)
                ans=append(ans,tmp)
            }
            return
        }
        if len(path)>k{
            return
        }
        for i:=idx;i<n;i++{
            path=append(path,i)
            sum+=i
            back_tracking(path,sum,i+1)
            path=path[:len(path)-1]
            sum-=i
        }
    }
    back_tracking([]int{},0,1)
    return ans
}

发表于 2023-03-08 23:45:24 回复(0)
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param k int整型
     * @param n int整型
     * @return int整型二维数组
     */
    private ArrayList<ArrayList> list_1109 = new ArrayList<>();

    private void dfs(int[] arr, ArrayList<Integer> list, int size, int target,
                     int sum, int index) {
        if (list.size() == size) {
            if (sum == target) {
                list_1109.add(new ArrayList(list));
            }
            return;
        }
        for (int i = index; i < arr.length; i++) {
            list.add(arr[i]);
            sum = sum + arr[i];
            dfs(arr, list, size, target, sum, i + 1);
            list.remove(list.size() - 1);
            sum = sum - arr[i];
        }
    }

    public int[][] combination(int k, int n) {
        int[] arr = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
        ArrayList<Integer> list = new ArrayList<>();
        dfs(arr, list, k, n, 0, 0);
        int[][] res = new int[list_1109.size()][];
        for (int i = 0; i < res.length; i++) {
            final ArrayList arrayList = list_1109.get(i);
            res[i] = new int[arrayList.size()];
            for (int j = 0; j < arrayList.size(); j++) {
                res[i][j] = (int) arrayList.get(j);
            }
        }
        return res;
    }
}

发表于 2022-11-09 21:47:34 回复(0)
function combination( k ,  n ) {
    let res = [];
    let path = [];
    backTracking(k, n, 0, 1);
    return res;
    
    function backTracking(k, n, sum, startIndex){
        if(path.length === k && sum === n){
            res.push([...path]);
            return;
        }
        if(sum > n){
            return;
        }
        for(let i = startIndex; i < n - (k - path.length) + 1; i++){
            sum += i;
            path.push(i);
            backTracking(k, n, sum, i + 1);
            sum -= i;
            path.pop();
        }
    }
}

发表于 2022-07-16 21:53:24 回复(0)
//回溯利用
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param k int整型 
     * @param n int整型 
     * @return int整型二维数组
     */
    ArrayList<ArrayList<Integer>>res=new ArrayList<>();
    List<Integer>path=new LinkedList<>();
    public int[][] combination (int k, int n) {
        // write code here
        backtracking(k,n,1);
        int [][]nums=new int[res.size()][k];
       
        for(int i=0;i<res.size();i++){
            ArrayList<Integer>l=res.get(i);
            for(int j=0;j<l.size();j++){
                nums[i][j]=l.get(j);
            }
        }
        return nums;
        
    }
    public void backtracking(int k,int n,int start){
        if(path.size()==k){
            if(n==0){
                res.add(new ArrayList<>(path));
               
            }
            return;
        }
        for(int i=start;i<=9-(k-path.size())+1;i++){
            if(n-i<0){
                break;
            }
            path.add(i);
            backtracking(k,n-i,i+1);
            path.remove(path.size()-1);
            
        }
    }
}

发表于 2022-05-07 21:23:58 回复(0)
主要实现还是回溯迭代方法。主要考虑回溯点的位置,确定界点

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param k int整型 
 * @param n int整型 
 * @return int整型二维数组
 */
function combination( k ,  n ) {
    // write code here
    dfcData(1, k, n, [])
    return resultArr
//     console.log(JSON.stringify(resultArr))
}
var resultArr = []
function dfcData(i, k, n, arr) {
   if(k < 0 || n < 0) {
       return;
   }
    if(n === 0 && k ===0) {
        const arrtemp = [...arr]
        resultArr.push(arrtemp)
        return;
    }
    for(let a = i; a <= 9; a++) {
        arr.push(a)
        dfcData(a+1, k-1, n-a, arr)
        arr.pop()
    }
}
module.exports = {
    combination : combination
};

发表于 2022-04-08 16:01:54 回复(0)
class Solution {
public:
    vector<vector<int>>tmp;vector<int>list;
    void dfs(int start,int k,int sum)
    {
        if(sum<=0){if(list.size()==k&&sum==0)tmp.push_back(list);}
         for(int i=start;i<=9;i++)
         {
             list.push_back(i);
             dfs(i+1,k,sum-i);
             list.pop_back();
         }
    }
    vector<vector<int> > combination(int k, int n) {
        dfs(1,k,n);
        return tmp;
    }
};

发表于 2022-01-05 06:55:56 回复(0)
要求是每种组合中不含有相同的数字,结果按字典序升序输出。
那么结果组合中,必定是升序排列,一个数字至少比前一个大1。
假设第一个数字是i,k个数,和是n,判断后续能否有合法组合的条件就是
(i+1) + (i+2) + ... + ((i+1)+(k-1)) <=n-i,这样才能保证后续有合法组合。

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param k int整型 
     * @param n int整型 
     * @return int整型vector<vector<>>
     */
    vector<vector<int> > combination(int k, int n) {
        lst.resize(k);
        
        serchCombin(k, n, 1);
        
        return result;
    }
    
private:
    vector<vector<int> > result;
    vector<int> lst;
    int idx=0;
    void serchCombin(int k, int n, int start) {
        if(1==k) {
            lst[idx]=n;
            result.push_back(lst);
            return;
        }
        --k;
        for(int i=start;((i+1)+(i+1+k-1))*k/2<=(n-i);++i) {
            lst[idx++]=i;
            serchCombin(k, n-i, i+1);
            --idx;
        }
    }
};


发表于 2021-12-17 10:17:47 回复(0)

问题信息

难度:
13条回答 1895浏览

热门推荐

通过挑战的用户

查看代码