簡體   English   中英

獲取所有數字等於其給定總和的n位數字

[英]Get all n-digit numbers whose sum of digits equals to given sum

我怎樣才能得到所有n位數字的總和等於給定的總和? 我需要最快的解決方案,因為n可以等於9,總和可以等於1000。

我已經在下面實現了解決方案,但是它太慢了...

List<int> l = new List<int>();
void findNDigitNumsUtil(int n, int sum, char[] ou, int index)
{
    if (index > n || sum < 0)
        return;
    if (index == n)
    {
        if (sum == 0)
        {
            ou[index] = '\0';
            string s = new string(ou);
            l.Add(Int32.Parse(s));
        }

        return;
    }

    for (int i = 0; i <= 9; i++)
    {
        ou[index] = (char)(i + '0');
        findNDigitNumsUtil(n, sum - i, ou,
                                index + 1);

    }
}

void findNDigitNums(int n, int sum)
{
    char[] ou = new char[n + 1];
    for (int i = 1; i <= 9; i++)
    {
        ou[0] = (char)(i + '0');
        findNDigitNumsUtil(n, sum - i, ou, 1);
    }
}

我需要最快的解決方案

不,您需要一個足夠快的解決方案。 您可能甚至不願意在定制硬件上花費一百萬美元來獲得最快的解決方案。

我怎樣才能得到所有n位數字的總和等於給定的總和?

在這里,我將為您提供一個稍微不同的問題的解決方案:

都是什么的序列n數字從0-9得出總和sum

這是不同的,因為它將0110視為長度為2的序列的總和,但01不是兩位數。

我將向您提示如何解決此較簡單的問題。 然后,您采用該解決方案,並將其適應於更困難的問題

首先,您能解決一位數字問題嗎? 那很容易。 如果n為0到9,則其數字總和為n的一位數字就是數字n ,否則沒有解決方案。

第二:假設N> 1。然后n位數字號碼那筆sum是:

  • 0后跟所有n-1個數字的sum
  • 1 ,隨后所有的n-1位數那筆sum-1
  • 2后跟所有加總到sum-2n-1個數字
  • ...
  • 9后跟所有sum-9n-1位數字

編寫解決該問題的實現,然后對其進行調整以解決您的問題。

您可以將n位數字視為n位數字的數組。 然后,您可以將特定數字增加到下一個數字,該數字也將相加。 逐步完成所有下一個答案,您已經生成了所有可能的組合。

使用生成器將每個n位數字組合生成為IEnumerable<int> (實際上是int[] ),首先從“最小”的n位數字組合產生總和,然后遍歷每個數字。

IEnumerable<IEnumerable<int>> DigitsToSum(int n, int sum) {
    if (sum > 9 * n)
        yield return Enumerable.Empty<int>();
    else {
        var ans = new int[n];

        void distribute(int wsum, int downto) {
            for (var j1 = n - 1; j1 > downto; --j1) {
                if (wsum > 9) {
                    ans[j1] = 9;
                    wsum -= 9;
                }
                else {
                    ans[j1] = wsum;
                    wsum = 0;
                }
            }
        }

        ans[0] = Math.Max(1, sum-9*(n-1));
        distribute(sum-ans[0], 0);

        bool nextAns() {
            var wsum = ans[n-1];
            for (var j1 = n - 2; j1 >= 0; --j1) {
                wsum += ans[j1];

                if (ans[j1] < Math.Min(9, wsum)) {
                    ++ans[j1];
                    distribute(wsum - ans[j1], j1);
                    return true;
                }
            }
            return false;
        }

        do {
            yield return ans;
        } while (nextAns());
    }
}

這比我的遞歸雙生成器解決方案(有點像@EricLippert的建議)迭代所有可能性(例如,使用Count() )要快得多。

您可以將數字放回去以獲得每個數字的最終數字字符串:

var ans = DigitsToSum(n, sum).Select(p => String.Join("", p));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM