zoukankan      html  css  js  c++  java
  • 输出满足条件的组合数

    问题:从 1 到 9 中选择 k 个不重复的数字,使它们相加起来等于 n。

    例1: 输入 k = 3, n = 7; 输出 [[1,2,4]]

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

    C#代码:

    using System;
    using System.Collections.Generic;
    
    public class Solution
    {
        /// <summary>
        /// 从1到9中,选择k个不同的数字,使其和等于n
        /// </summary>
        /// <param name="k">选择的数字个数</param>
        /// <param name="n">数字的和</param>
        /// <returns>复合条件的数字集合</returns>
        public IList<IList<int>> CombinationSum3(int k, int n)
        {
            int[] allNums = new int[10];
            int[] tagNums = new int[10];
            List<string> results = new List<string>();
            Solution p = new Solution();
    
            for (int i = 1; i < 10; i++)
            {
                allNums[i - 1] = i;
            }
    
            //这里备选数字集合为1-9这9个数
            p.Combine(allNums, 9, k, tagNums, k, results);
    
            IList<IList<int>> correctList = new List<IList<int>>();
            foreach (var res in results)
            {
                int sum = 0;
                List<int> correct = new List<int>();
    
                //计算各串数字的和
                for (int j = 0; j < res.Length; j++)
                {
                    sum += Convert.ToInt16(res[j].ToString());
                }
    
                if (sum == n)
                {
                    for (int m = 0; m <= res.Length - 1; m++)
                    {
                        correct.Add(Convert.ToInt16(res[m].ToString()));
                    }
                    correctList.Add(correct);
                }
    
                //清空sum的值
                sum = 0;
            }
            return correctList;
        }
    
        /// <summary>
        /// 输出给定数字范围内的所有组合(非排列)结果
        /// </summary>
        /// <param name="allNums">备选数字集合</param>
        /// <param name="needCount">在备选数字集合中,选择 needCount 个中数字来进行再次选择</param>
        /// <param name="childCount">取 childCount 个数字进行组合</param>
        /// <param name="tagNums">存放每次选中的 childCount 个数字在备选数字集合中的位置</param>
        /// <param name="backupChildCount">存放 childCount 的值</param>
        /// <param name="results">所有组合(非排列)结果</param>
        public void Combine(int[] allNums, int needCount, int childCount, int[] tagNums, int backupChildCount, List<string> results)
        {
            for (int i = needCount; i >= childCount; i--)
            {
                //选择第一个数字,记录它在 allNums 数组中的位置
                tagNums[childCount - 1] = i - 1;
    
                //如果选中的数字个数未达到 childCount 个,则继续选择下一个
                if (childCount > 1)
                {
                    Combine(allNums, i - 1, childCount - 1, tagNums, backupChildCount, results);
                }
                else
                {
                    string res = "";
                    for (int j = 0; j <= backupChildCount - 1; j++)
                    {
                        res += allNums[tagNums[j]].ToString();
                    }
                    results.Add(res);
                }
            }
        }
    }

    参考资料:http://bbs.csdn.net/topics/390242147

    输出组合数(回溯法)

    public class Solution
    {
        public const int MAXN = 100;
        public int[] a = new int[MAXN];
        static void Main(string[] args)
        {
            Solution p = new Solution();
            p.comb(9, 3);
            System.Console.ReadKey();
        }
    
        void comb(int m, int r) /* 求从自然数1到m中任取3个数的所有组合子程序 */
        {
            int i, j;
            i = 0; a[i] = 1;        /* 初始规模为1时,a[0]为1 */
            do
            {
                if (a[i] - i <= m - r + 1) /* 还可以向前试探 */
                {
                    if (i == r - 1)  /* 当前候选解的视图满足问题的规模要求,找到一个解 */
                    {
                        for (j = 0; j < r; j++)
                            System.Console.Write(a[j] + " ");
                        System.Console.Write("
    ");
                        a[i]++;          /* 考查当前规模的下一个候选解 */
                        continue;
                    }
                    i++;
                    a[i] = a[i - 1] + 1;
                }
                else
                {              /* 当前规模的候选解已经全部考查完毕,则应回溯,缩小规模 */
                    if (i == 0)      /* 回溯至初始规模,则已经全部找到了解 */
                        return;
                    a[--i]++;     /* 缩小规模,考查下一个候选解 */
                }
            } while (true);
        }
    }


    参考资料:软件设计师考试辅导教程

  • 相关阅读:
    npropress进度条插件的使用
    让img图片像背景一样显示
    vue-cli3配置多页面入口
    7中漂亮的纯css字体
    速查手册
    推荐系统架构
    leetcode 172. 阶乘后的零
    C++ string和int互相转换
    特征分解
    线性代数基础
  • 原文地址:https://www.cnblogs.com/hellowzl/p/5887408.html
Copyright © 2011-2022 走看看