繁体   English   中英

3位数字组合0-9算法如何工作?

[英]How does 3 digit number combinations 0-9 algorithm work?

#include<stdio.h>   
int main()
{
    int i, j, k;
    for (i = 0; i <= 7; i++)
    {
        for (j = i+1; j <= 8; j++)
        {
            for (k = j+1; k <= 9; k++)
            {
                printf("%d%d%d\n", i, j, k);
            }
        }
    }
}

我有这个算法。 它生成所有120个唯一编号。 也许我很笨,但是我不明白一件简单的事。 如果我从两个内部循环变量初始化中删除+1,我将收到720个唯一组合。 有了这个+1,我将收到120,不再重复。 因此,它会清除数字,因此不会出现例如517和715这样的数字。 有人可以解释一下如何向内部循环中添加+1来删除所有不同的排列并只留下一个吗? 因为必须至少有6组唯一的120个数字。

您只获得一组数字,那些数字以升序排列。 因为您从012开始,然后开始将最后一位数字递增到019然后继续从023 +1将下一位数字增加一位,因此不会相同。 如果您不使用它,则从000开始,直到789为止(不包括所有“ 90”)。

编辑有关评论:

在生成的数字中,所有数字均按升序排列。 因此,最后一个总是大于其他两个。 因此,如果您从012开始并开始增加,则会得到所有包含01数字,然后全部包含02 ,依此类推。 直到您将所有可能性都设置为0为止,然后您便以这种方式转到123 ,没有重复项。

当您打印第一组数字时,您具有:

i j k --> i i+1 j+1 --> i i+1 i+2 --> 0 1 2,

在第一个完成k循环之后,您将拥有:

i j k --> 0 1 9.

然后,继续执行j -loop:

i j k --> 0 2 3.

如果jk循环的初始值未增加,则您将具有:

i j k --> i i i --> 0 0 0
....
i j k --> 0 0 9
i j k --> 0 1 1,

并且集合将包含重复的数字。

该算法获取所有三个唯一数字的集合,因为它首先找到所有以0 1开头的集合,然后找到所有以0 2 ,...开头的集合,然后是所有以1 2开头的集合。 ...,最后所有以7 8开头的集合,其中只有一个: 7 8 9

ijk上设置的限制在其中起作用。 最后一个集合是7 8 9 ,因此i限制为最大值7, j限制为8, k限制为9。当第一次继续执行i -loop时:

i j k --> 0 8 9
i j k --> 1 2 3

没有更多的以0 8开头的唯一集合,也没有以0 9开头的唯一集合(我们已经有了0 1 9 ,..., 0 8 9 ,证明了j <= 8的极限),所以现在我们拥有以0开头的所有唯一集合,并开始查找以1开头的所有唯一集合。 第一个是:

i j k --> i i+1 i+2 --> 1 2 3.

系统计数

我认为将这里发生的事情视为“摆脱重复”或某种排序是错误的。 这是关于系统计数。 我们要计算三位数的唯一集合的数量。 集合1 2 3 3 2 11 3 2是等效的,因为它们包含相同的成员,因此我们不想列出所有三个,而仅列出其中之一。 这些数字集不包含重复项,即1 1 2在此上下文中不是集合。 我们可以自由选择一个方便的标准来选择要计数的集合,并且我们选择按数字升序对(有序)集合进行计数。 注意,我们不对它们进行排序,我们只是对它们进行计数。

所采用的策略是列出组合,就好像它们是三位数字一样,从最小到最大。 自然地,列表从最小的可能性0 1 2 请注意,以数字d开头的最小“数字”是d d+1 d+2 ,而最大的此类“数字”是d 8 9 所有这些“数字”中最大的是7 8 9 这些观察为我们提供了循环条件的极限。

将此三位数视为计数器。 通过系统地浏览允许的组合,我们可以列出所有升序的三位数“数字”。 +1的原因是我们选择按数字升序对“数字”进行计数。 我们还可以选择按降序对“数字”进行计数。

想一想,这可能对您来说是一个好练习:修改算法以按降序显示数字。 这可能有助于巩固您的理解。

我多挖了一点。 并发现接下来的事情:

我们有1000个3位数字:

000-999

共有720种可能的3位数组合,使用数字0-9:

10x9x8 = 720个组合

排列3位数字的方法有6种:

3x2x1 = 6

这意味着720个数字中有重复项。 例如,这些来自720个组合的数字集被视为重复项:

157、175、517、571、715、751

目的是消除带有嵌套循环的重复项。

#include<stdio.h>
int main(void)
{
    int i, j, k;

    i = 0;
    while (i <= 9)
    {
        j = i + 1;
        while (j <= 9)
        {
            k = j + 1;
            while(k <= 9)
            {
                printf("%d%d%d\n", i, j, k);
                k++;
            }
            j++;
        }
        i++;
    }
}

如果您将+1替换为0,如下所示:

j = i + 1; with j = 0;

k = j + 1; k = 0;

您将生成所有1000个数字。

如果另外,在最里面的循环中放置一个if语句:

while(k <= 9)
{
    if(i != j && i != k && j != k)
    {
        printf("%d%d%d\n", i, j, k);
    }
    k++;
}

然后您将收到720个组合。

但是有了这些+1,我们就得到了降序排序。 像这样:

012, 013, 014, 015, 016, 017, 018, 019
023, 024, 025, 026, 027, 028, 029
034, 035, 036, 037, 038, 039
045, 046, 047, 048, 049
056, 057, 058, 059
067, 068, 069
078, 079
089

内循环结束后,它将再次从123开始。

因此,如果我正确理解此+1的作用,那就是降序编号。

因为我们从0开始,所以在第一行中生成8个数字。 而且,在每个循环周期中,每次连续进行的总循环次数减少了一个数字。

这给了我们一些数学魔术,摆脱了所有重复:)

基本上,因为我们生成数字和数字+1,所以我们将始终收到唯一的数字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM