首页 > 解决方案 > 使用尽可能少的空间连续分布点

问题描述

我有一行最多可以包含N点。我想x使用尽可能少的空间从中心向外分布该行内的点。

我设法在行内均匀分布点,但它使用了所有可用空间。使用公式floor((i+0.5)*N/x),我得到以下结果,考虑N=9

4 
2 6 
1 4 7 
1 3 5 7 
0 2 4 6 8 
0 2 3 5 6 8 
0 1 3 4 5 7 8 
0 1 2 3 5 6 7 8 
0 1 2 3 4 5 6 7 8

以下是上述输出中显示的索引的示例图形表示:

均匀分布在四面八方

我想基本上限制点从中心向外太远,所以我得到的结果更像:

4 
3 5 
3 4 5 
2 3 5 6 
2 3 4 5 6 
1 2 3 5 6 7 
1 2 3 4 5 6 7 
0 1 2 3 5 6 7 8 
0 1 2 3 4 5 6 7 8

以下是上述输出中显示的索引的示例图形表示:

从中心均匀分布

我正在使用 Java,这是我当前的代码

int rowLength = 9;

for (int points = 0; points <= rowLength; points++) {
    for (float i = 0; i < points; i++) {
        double result = Math.floor((i + 0.5) * rowLength / points);

        System.out.print((int) result + " ");
    }

    System.out.println();
}

我怎样才能最好地实现第二张图片中显示的结果,以便我的代码输出与第二个示例输出相匹配?

标签: javapointspacing

解决方案


好的,让我们看一下图片。对我来说,似乎有几行有共同点:

彩色图像

观察:

  • 蓝线的中间点被填充,橙色线的中间为空。
  • 蓝色的是奇数,橙色的是偶数。
  • 左边的空间是
    • 在奇数情况下:(rowLength - points)/2,例如 (9-1)/2 = 4
    • 在偶数情况下:(rowLength -points -1)/2,例如 (9-2-1)/2 = 3

让我们把它放到代码中。我在这里使用 C#,但 Java 应该非常相似:

int rowLength = 9;
for (int points = 0; points <= rowLength; points++) {
    bool isOdd = points%2 == 1;
    if (isOdd)
    {
        int spaceOnSide = (rowLength-points)/2;
        for (int i=0; i<points;i++)
        {
            Console.Write(""+(i+spaceOnSide)+" ");
        }
    }
    else // even
    {
        int spaceOnSide = (rowLength-1-points)/2;
        for (int i=0; i<points/2;i++)
        {
            Console.Write(""+(i+spaceOnSide)+" ");
        }

        for (int i=points/2; i<points;i++)
        {
            Console.Write(""+(i+spaceOnSide+1)+" ");
        }           
    }
    Console.WriteLine();
}

正如观察告诉我们的那样,这是非常直截了当的。

鉴于该代码,我们可以使用一些技巧:

  1. 由于整数除法,该行

    int spaceOnSide = (rowLength-1-points)/2;
    

    给出相同的结果

    int spaceOnSide = (rowLength-points)/2;
    

    (没有-1)。

  2. 我们可以将奇数情况下的 for 循环分成两部分:

    for (int i=0; i<points/2;i++)
    {
        Console.Write(""+(i+spaceOnSide)+" ");
    }
    for (int i=points/2; i<points;i++)
    {
        Console.Write(""+(i+spaceOnSide)+" ");
    }       
    

    起初这听起来适得其反,但请看第 3 步。

  3. 完成该更改后,奇数部分和偶数部分看起来非常相似。这真的是重复的代码。唯一的区别在于+1部分。我们可以在那里添加 if 语句作为三元运算符:

    对于 (int i=0; 我

  4. 如果你不喜欢三元运算符,你可以去掉它:

    (isOdd?0:1)
    

    等于

    (points+1)%2
    

最后你的代码很简单

int rowLength = 9;
for (int points = 0; points <= rowLength; points++) {
    int spaceOnSide = (rowLength-points)/2;
    for (int i=0; i<points/2;i++)
    {
        Console.Write(""+(i+spaceOnSide)+" ");
    }
    for (int i=points/2; i<points;i++)
    {
        Console.Write(""+(i+spaceOnSide+(points+1)%2)+" ");
    }                   
    Console.WriteLine();
}

推荐阅读