如何获得可以使用给定数字形成的所有可能的 n 位数字?

Posted

技术标签:

【中文标题】如何获得可以使用给定数字形成的所有可能的 n 位数字?【英文标题】:How to get all possible n-digit numbers that can be formed using given digits? 【发布时间】:2012-03-27 14:01:16 【问题描述】:

我正在编写面临此问题的大型应用程序的一部分。我将通过呈现一个类似的普通场景将所有细节从所有细节中抽象出来。

给我 n(在运行时形成的数字的位数)。

我还得到了一个数字列表,比如 2,4,8,9。

我必须从上面给定长度的列表中形成所有可能的数字。

例如如果 n = 3 并且列表 = 4, 5, 6

那么可能的数字是:

444,
445,
446,
454,
455,
456,
464,
465,
466, 

等等……

任何帮助将不胜感激!

问候

沙恨沙

【问题讨论】:

因为答案在您的问题的解释上有所不同:您能指定输出应该是什么数据类型吗? 【参考方案1】:

您可以使用递归。 假设您可以使用的数字在一个数组中。

C#代码:

static int[] digits = new int[] 4, 5, 6;

static void Rec(int current, int numDigits) 
    if(numDigits==0)
        Console.WriteLine(current);
    else
        foreach(int x in digits)
            Rec(current*10+x, numDigits-1);

然后调用:

static void Main(string[] args)
    Rec(0, 3);

【讨论】:

所有答案都很好,但我觉得这是最优雅的一个。非常感谢@petar Ivanov! (:【参考方案2】:

使用递归函数。这是javascript中的一个例子......

var result;
function recurse(n,lst,s)
  var i,c;  
  for (i=0; i<lst.length; i++)
    if(n>1)recurse(n-1,lst,s+lst[i]);
    else result.push(s+lst[i])
  

function generate(n,lst)
  result=[];
  if(n>0 && lst.length>0)
    for(var i=0; i<lst.length; i++)lst[i]=''+lst[i];
    recurse(n,lst,'')
  
  return result

generate(3,[4,5,6]);

【讨论】:

【参考方案3】:

我的方法如下:

list combine(list a, list b)

    list c;
    for ( i = 0, i < list.size(), ++i )
    
        for ( j = 0, j < list.size(), ++j )
            c.add( a[i] * pow(10,log_10(b[j]) + 1) + b[j] );
    
    return c;

然后对于n位问题:

list nDigit(list a, int n)

    list out;
    out = combine(a, a);
    for ( i = 1, i < n, ++i )
        out = combine(a, out);
    return out;

这应该会变魔术。 代码应该是不言自明的,如果不是,请发表评论。

您必须注意列表项是否可以超过一个数字。然后需要在 combine 函数中添加以下内容:

[....]
for ( j = 0, j < list.size(), ++j )

    if ( log_10(a[i]) + log_10(b[j]) + 1 <= n )
        c.add( a[i] * pow(10,log_10(b[j]) + 1) + b[j] );

[....]

当然还有 n 给 combine 函数。

最后在 nDigit 你必须检查是否有长度小于 n 的组合

【讨论】:

将数字字符串视为整数非常容易溢出。为什么不使用字符串和索引来代替数字和对数? Shahensha 从来没有提到它必须是字符串,所以这个算法是为整数工作而设计的【参考方案4】:

您的任务相当于以不同于 10 的基数进行计数,如以下 C++ 程序所示:

#include <vector>
#include <iostream>

using std::vector;

unsigned int pow(unsigned int n, unsigned int m)

    unsigned int to_ret = 1;
    for (unsigned int i = 0; i < m; i++)
        to_ret *= n;
    return to_ret;


void print_all(vector<unsigned int> sym, unsigned int n)

    const unsigned int m = sym.size();
    unsigned int max = pow(m, n);
    char *text = new char[n + 1];
    text[n] = '\0';
    for (unsigned int i = 0; i < max; i++) 
        unsigned int to_print = i;
        for (unsigned int j = 1; j <= n; j++) 
            text[n - j] = sym[to_print % m];
            to_print /= m;
        
        std::cout << text << std::endl;
    
    delete[] text;


int main(int argc, char **argv)

    vector<unsigned int> a('1','2','3','4','5');
    print_all(a, 5);
    return 0;

对于足够高的nm 值,max 很容易溢出这种方法的明显问题。您可以通过使用m 链表数组模拟计数来解决这个问题,该数组必须表示“数字”。

【讨论】:

【参考方案5】:

我编写了以下 F# 代码来解决这个问题:

let rec variations rank xs = 
    match rank with
    | 1 -> 
        seq 
            for x in xs do
            yield [x]
        

    | _ -> 
        seq 
            for x in xs do
            for y in variations (rank-1) xs do   
            yield x::y
        

所以,

variations 3 (seq 4..6)
|> Seq.iter (printfn "%s")

将打印

444
445
446
454
455
...
666

所有 27 个值

【讨论】:

以上是关于如何获得可以使用给定数字形成的所有可能的 n 位数字?的主要内容,如果未能解决你的问题,请参考以下文章

您能否帮助我了解如何使用 +- 运算符找到从 1 到 N 的一组给定数字的所有可能组合 [重复]

如何计算数字/位数组的所有可能性(在 python 或任何语言中)

给定一个掩码数,计算所有可能被 n 整除的数

如何计算给定数字的位数?

如何在 O(n) 时间内找到与 n 个不同数字的中位数最近的 k 个邻居?

给定N个非0的个位数字,用其中任意2个数字都可以组合成1个2位的数字。要求所有可能组合出来的2位数字的和。例如给定258,则可以组合出:252852588285,它们的和为330。