【问题标题】:Solve Number Puzzle with C and Java用 C 和 Java 解决数字难题
【发布时间】:2013-11-12 09:21:34
【问题描述】:

这个问题是我从另一个论坛翻译成英文的,我觉得很有趣,然后写了一个Java解决方案。发现在处理像 10000000 这样的大数字时存在一些堆大小问题。与我自己的相比,我想寻求一些非常聪明的解决方案。

原帖为中文。我根据自己的理解对其进行了一些修改,以使其更清晰。 http://zhidao.baidu.com/question/1637660984282265740.html?sort=6&old=1#here

下面是谜题:

10000 rows of numbers;
1 row: 2,4,6,8...2K(2K<=10000000); (numbers no repeats for this row)
2 row: 3,3,6,6,9,9...3K(3K<=10000000); (starting from this row, each number repeats 2 times and a multiple which has something to do with row number (2XrowNumber-1) to be specificaly)
3 row: 5,5,10,10,15,15...5K(5K<=10000000);
and following 7K,9K,11K,13K....until
10000 row: 19999,19999,39998,39998....19999K,19999K (19999K<=10000000);

这就是下一部分要使用的所有行。现在我们将计算从第 1 行和第 2 行开始的数字的重复次数:

整数 w1 是第 1 行和第 2 行中数字的重复次数。例如,考虑第 1 行数字 2,4,6 和第 2 行数字 3,3,6,6。那么到目前为止的重复次数将是 3,因为 6 已经在第 1 行并在第 2 行出现了 2 次,而 3 在第 2 行出现了 2 次;

Integer w2 is the repeat times of numbers in row 1 and row 2 and row 3. 
Integer w3 is the repeat times of numbers in row 1 and row 2 and row 3 and row 4. 
......
Integer w9999 is the repeat times of numbers of row 1,row 2,row 3 .....row 10000.

现在打印出所有整数,w1,w2....w9999;

我想出了一个 Java 解决方案,但是我遇到了堆大小问题,因为 10000000 太大并且内存不够。所以我只用 10000 代替 10000000,用 10 代替 10000。下面是我用 Java 写的。我想应该是对的(如果不对,请指出):

    Set nums = new HashSet();
    int max = 10000;
    int row = 10;
    for (int i=2;i<=max;i+=2){
        nums.add(new Integer(i));
    }
    int nums_size = nums.size();
    int w = 0;
    for (int i=2;i<=(row);i++){
        int tmp_count = 0;
        int self_count = 0;
        for (int j=(2*i-1);j<=max;j+=(2*i-1)){
            nums.add(new Integer(j));
            self_count++;
            if (nums.size()==nums_size){
                tmp_count++;
            } else {
                nums_size = nums.size();
            }
        }           
        w += tmp_count;
        w += self_count;
        System.out.println("w"+(i-1)+": "+w);
    }

我的问题是

  1. 如何在 Java 中获得更好的解决方案(如果有)?
  2. 如何在 C 中实现 因为我记得 C 中没有 Set 类。 (进口第三 党图书馆不是首选)?

谢谢。

【问题讨论】:

  • 我很惊讶人们已经放弃投票,甚至没有告诉我为什么?
  • 这很愚蠢,为什么会被否决——也许有人不知道答案。
  • 每一行的数字有规律吗?
  • @Felix 第一行呢?没有重复?
  • 重复次数是什么意思?它是一个数字的最大出现次数吗?对于 w1(row1=2,4,6 & row2=3,3,6,6) 2 出现 1 次,3 出现 2 次,4 出现 1 次,6 出现 3 次,所以 w1 = 3。我明白了吗正确吗?

标签: java c algorithm math puzzle


【解决方案1】:

这是您的代码的简化版本。因为它不使用HashSet,所以用它创建一个C版本应该没有问题了。

int max = 10000;
int row = 10;
boolean[] seen=new boolean[max+1];
for(int i=2;i<=max;i+=2) seen[i]=true;
int w = 0;
for(int i=2;i<=(row);i++) {
    int self_count = 0;
    for(int j=(2*i-1);j<=max;j+=(2*i-1)) {
        self_count++;
        if(seen[j]) w++; else seen[j]=true;
    }
    w += self_count/2;
    System.out.println("w"+(i-1)+": "+w);
}

【讨论】:

  • 我明白了你的想法,我认为使用原语会更好。保存了很多回忆。我怎么能忘记使用基础知识?我想我需要从头开始学习。谢谢。
  • 您认为有更快的方法吗?
  • 因为从第 3 行向上的每个单元格都有 (2*r-1)*c 的形式,您可以跳过很多值,因为“c2*«a previous row»-1) 的倍数”的单元格值低于最大值上一行。也许有一个完全分析的解决方案,但我没有深入研究它来找出答案。
【解决方案2】:

不是答案,而是提示:尝试使用最小公倍数。

例如,LCM(5,3)=15,15 是第 2 行和第 3 行的第一个元素。LCM(2,15)=30,30 是前 3 行中的第一个元素.

您最终会到达第 r 行,其中前 r 行的第一个元素的 LCM 超过 10,000,000,此时这些行中的每一行都没有数字显示。

【讨论】:

  • 我想这会有点慢,如果:对于每行 n(n>2) 中的每个数字,您需要从第一行开始计算最小公倍数,直到行之后的每一行n-1。让我知道我是否错了。我在想我的方法可能很快。不知道有没有更快的方法。
  • @Felix 您不需要计算所有这些 LCM; LCM(1,2,3,4,...,n) = LCM(LCM(1,2,3,4,...,n-1), n)。也就是说在得到前r行的LCM之后,前r+1行的LCM就是一个额外的LCM操作。
  • LCM(2,3)=6; LCM(2,3,5)=LCM(6,5)=30; LCM(2,3,5,7) = LCM(30,7)=210; LCM(2,3,5,7,9) = LCM(210,9)=630;等等……
  • 好的..我对你所说的有了更好的理解。我会尝试看看这种方法是否更快。感谢您的提示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
  • 2023-02-02
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多