将线分成间隔的算法

时间:2014-07-25 13:23:45

标签: algorithm

我正在寻找一种将整数范围[0-n]分成固定数量的k个间隔(不一定都是相同长度)的算法。因此,如果n = 15且k = 8,那么我想将0 - 15分成8个区间,我可以这样做: 0 2 4 6 8 10 12 14 15

如果我想分成10个区间,我可以这样做: 0 2 3 5 7 9 11 12 13 14 15

什么是一个简单的算法,可以生成一个数组[0 .. k],指定每一步的跳转?

编辑: 1< = k< = n。我想要的是吐出一个从[0] = 0到[k] = n的数组[0 .. k]。所以端点固定为0和n。如果间隔尽可能接近相同长度也是好的。

5 个答案:

答案 0 :(得分:2)

如果您希望间隔尽可能均匀,请考虑使用线条绘制算法(例如bresenham's line algorithm),从点(0,0)到(n,k)绘制一条线并选择不同的x坐标。

答案 1 :(得分:1)

s = starting value
n = ending value
k = num of values

其中

s <= n以确保有效范围

k > 1必须有起点和终点

n-s+1 >= k以确保存在非重复值

让我们定义x = 1 + ((n - s + 1)-k)/(k-1)

因此对于0 <= i < k我们有a[i]=round(s+i*x)

JS示例代码。从Windows命令行测试为cscript //nologo steps.js

for (var s = 0 ; s < 10 ; s++ )
for (var n = s ; n < s + 15 ; n++ )
for (var k = 2 ; k <= ( n - s + 1 ) ; k++ ) printRanges( s, n, k );


function printRanges( start, end, steps ){

    var s=start;
    var n=end;
    var k=steps;

    WScript.StdOut.Write('s='+s+', n='+n+', k='+k+ ' : ');

    var x=1+((n-s+1)-k)/(k-1);

    for (var i=0; i < k; i++) {
        WScript.StdOut.Write( Math.round(s + i * x ) + ' ' );
    };
    WScript.StdOut.WriteLine('')
}

结果

s=0, n=1, k=2 : 0 1 
s=0, n=2, k=2 : 0 2 
s=0, n=2, k=3 : 0 1 2 
s=0, n=3, k=2 : 0 3 
s=0, n=3, k=3 : 0 2 3 
s=0, n=3, k=4 : 0 1 2 3 
s=0, n=4, k=2 : 0 4 
s=0, n=4, k=3 : 0 2 4 
s=0, n=4, k=4 : 0 1 3 4 
s=0, n=4, k=5 : 0 1 2 3 4 
s=0, n=5, k=2 : 0 5 
s=0, n=5, k=3 : 0 3 5 
s=0, n=5, k=4 : 0 2 3 5 
s=0, n=5, k=5 : 0 1 3 4 5 
s=0, n=5, k=6 : 0 1 2 3 4 5 
s=0, n=6, k=2 : 0 6 
s=0, n=6, k=3 : 0 3 6 
s=0, n=6, k=4 : 0 2 4 6 
s=0, n=6, k=5 : 0 2 3 5 6 
s=0, n=6, k=6 : 0 1 2 4 5 6 
s=0, n=6, k=7 : 0 1 2 3 4 5 6 
s=0, n=7, k=2 : 0 7 
s=0, n=7, k=3 : 0 4 7 
s=0, n=7, k=4 : 0 2 5 7 
s=0, n=7, k=5 : 0 2 4 5 7 
s=0, n=7, k=6 : 0 1 3 4 6 7 
s=0, n=7, k=7 : 0 1 2 4 5 6 7 
s=0, n=7, k=8 : 0 1 2 3 4 5 6 7 
s=0, n=8, k=2 : 0 8 
....
s=4, n=15, k=2 : 4 15 
s=4, n=15, k=3 : 4 10 15 
s=4, n=15, k=4 : 4 8 11 15 
s=4, n=15, k=5 : 4 7 10 12 15 
s=4, n=15, k=6 : 4 6 8 11 13 15 
s=4, n=15, k=7 : 4 6 8 10 11 13 15 
s=4, n=15, k=8 : 4 6 7 9 10 12 13 15 
s=4, n=15, k=9 : 4 5 7 8 10 11 12 14 15 
s=4, n=15, k=10 : 4 5 6 8 9 10 11 13 14 15 
s=4, n=15, k=11 : 4 5 6 7 8 10 11 12 13 14 15 
s=4, n=15, k=12 : 4 5 6 7 8 9 10 11 12 13 14 15 
....
s=4, n=17, k=2 : 4 17 
s=4, n=17, k=3 : 4 11 17 
s=4, n=17, k=4 : 4 8 13 17 
s=4, n=17, k=5 : 4 7 11 14 17 
s=4, n=17, k=6 : 4 7 9 12 14 17 
s=4, n=17, k=7 : 4 6 8 11 13 15 17 
s=4, n=17, k=8 : 4 6 8 10 11 13 15 17 
s=4, n=17, k=9 : 4 6 7 9 11 12 14 15 17 
s=4, n=17, k=10 : 4 5 7 8 10 11 13 14 16 17 
s=4, n=17, k=11 : 4 5 7 8 9 11 12 13 14 16 17 
s=4, n=17, k=12 : 4 5 6 8 9 10 11 12 13 15 16 17 
s=4, n=17, k=13 : 4 5 6 7 8 9 11 12 13 14 15 16 17 
s=4, n=17, k=14 : 4 5 6 7 8 9 10 11 12 13 14 15 16 17 
s=4, n=18, k=2 : 4 18 
s=4, n=18, k=3 : 4 11 18 
s=4, n=18, k=4 : 4 9 13 18 
s=4, n=18, k=5 : 4 8 11 15 18 
s=4, n=18, k=6 : 4 7 10 12 15 18 
s=4, n=18, k=7 : 4 6 9 11 13 16 18 
s=4, n=18, k=8 : 4 6 8 10 12 14 16 18 
s=4, n=18, k=9 : 4 6 8 9 11 13 15 16 18 
s=4, n=18, k=10 : 4 6 7 9 10 12 13 15 16 18 
s=4, n=18, k=11 : 4 5 7 8 10 11 12 14 15 17 18 
s=4, n=18, k=12 : 4 5 7 8 9 10 12 13 14 15 17 18 
s=4, n=18, k=13 : 4 5 6 8 9 10 11 12 13 15 16 17 18 
s=4, n=18, k=14 : 4 5 6 7 8 9 10 12 13 14 15 16 17 18 
s=4, n=18, k=15 : 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 
....
s=9, n=10, k=2 : 9 10 
s=9, n=11, k=2 : 9 11 
s=9, n=11, k=3 : 9 10 11 
s=9, n=12, k=2 : 9 12 
s=9, n=12, k=3 : 9 11 12 
s=9, n=12, k=4 : 9 10 11 12 
s=9, n=13, k=2 : 9 13 
s=9, n=13, k=3 : 9 11 13 
s=9, n=13, k=4 : 9 10 12 13 
s=9, n=13, k=5 : 9 10 11 12 13 
s=9, n=14, k=2 : 9 14 
s=9, n=14, k=3 : 9 12 14 
s=9, n=14, k=4 : 9 11 12 14 
s=9, n=14, k=5 : 9 10 12 13 14 
s=9, n=14, k=6 : 9 10 11 12 13 14 
s=9, n=15, k=2 : 9 15 
s=9, n=15, k=3 : 9 12 15 
s=9, n=15, k=4 : 9 11 13 15 
s=9, n=15, k=5 : 9 11 12 14 15 
s=9, n=15, k=6 : 9 10 11 13 14 15 
s=9, n=15, k=7 : 9 10 11 12 13 14 15 
s=9, n=16, k=2 : 9 16 
s=9, n=16, k=3 : 9 13 16 
s=9, n=16, k=4 : 9 11 14 16 
s=9, n=16, k=5 : 9 11 13 14 16 
s=9, n=16, k=6 : 9 10 12 13 15 16 
s=9, n=16, k=7 : 9 10 11 13 14 15 16 
s=9, n=16, k=8 : 9 10 11 12 13 14 15 16 
s=9, n=17, k=2 : 9 17 
s=9, n=17, k=3 : 9 13 17 
s=9, n=17, k=4 : 9 12 14 17 
s=9, n=17, k=5 : 9 11 13 15 17 
s=9, n=17, k=6 : 9 11 12 14 15 17 
s=9, n=17, k=7 : 9 10 12 13 14 16 17 
s=9, n=17, k=8 : 9 10 11 12 14 15 16 17 
s=9, n=17, k=9 : 9 10 11 12 13 14 15 16 17 
s=9, n=18, k=2 : 9 18 
s=9, n=18, k=3 : 9 14 18 
s=9, n=18, k=4 : 9 12 15 18 
s=9, n=18, k=5 : 9 11 14 16 18 
s=9, n=18, k=6 : 9 11 13 14 16 18 
s=9, n=18, k=7 : 9 11 12 14 15 17 18 
s=9, n=18, k=8 : 9 10 12 13 14 15 17 18 
s=9, n=18, k=9 : 9 10 11 12 14 15 16 17 18 
s=9, n=18, k=10 : 9 10 11 12 13 14 15 16 17 18 
s=9, n=19, k=2 : 9 19 
s=9, n=19, k=3 : 9 14 19 
s=9, n=19, k=4 : 9 12 16 19 
s=9, n=19, k=5 : 9 12 14 17 19 
s=9, n=19, k=6 : 9 11 13 15 17 19 
s=9, n=19, k=7 : 9 11 12 14 16 17 19 
s=9, n=19, k=8 : 9 10 12 13 15 16 18 19 
s=9, n=19, k=9 : 9 10 12 13 14 15 17 18 19 
s=9, n=19, k=10 : 9 10 11 12 13 15 16 17 18 19 
s=9, n=19, k=11 : 9 10 11 12 13 14 15 16 17 18 19 
s=9, n=20, k=2 : 9 20 
s=9, n=20, k=3 : 9 15 20 
s=9, n=20, k=4 : 9 13 16 20 
s=9, n=20, k=5 : 9 12 15 17 20 
s=9, n=20, k=6 : 9 11 13 16 18 20 
s=9, n=20, k=7 : 9 11 13 15 16 18 20 
s=9, n=20, k=8 : 9 11 12 14 15 17 18 20 
s=9, n=20, k=9 : 9 10 12 13 15 16 17 19 20 
s=9, n=20, k=10 : 9 10 11 13 14 15 16 18 19 20 
s=9, n=20, k=11 : 9 10 11 12 13 15 16 17 18 19 20 
s=9, n=20, k=12 : 9 10 11 12 13 14 15 16 17 18 19 20 
s=9, n=21, k=2 : 9 21 
s=9, n=21, k=3 : 9 15 21 
s=9, n=21, k=4 : 9 13 17 21 
s=9, n=21, k=5 : 9 12 15 18 21 
s=9, n=21, k=6 : 9 11 14 16 19 21 
s=9, n=21, k=7 : 9 11 13 15 17 19 21 
s=9, n=21, k=8 : 9 11 12 14 16 18 19 21 
s=9, n=21, k=9 : 9 11 12 14 15 17 18 20 21 
s=9, n=21, k=10 : 9 10 12 13 14 16 17 18 20 21 
s=9, n=21, k=11 : 9 10 11 13 14 15 16 17 19 20 21 
s=9, n=21, k=12 : 9 10 11 12 13 14 16 17 18 19 20 21 
s=9, n=21, k=13 : 9 10 11 12 13 14 15 16 17 18 19 20 21 
s=9, n=22, k=2 : 9 22 
s=9, n=22, k=3 : 9 16 22 
s=9, n=22, k=4 : 9 13 18 22 
s=9, n=22, k=5 : 9 12 16 19 22 
s=9, n=22, k=6 : 9 12 14 17 19 22 
s=9, n=22, k=7 : 9 11 13 16 18 20 22 
s=9, n=22, k=8 : 9 11 13 15 16 18 20 22 
s=9, n=22, k=9 : 9 11 12 14 16 17 19 20 22 
s=9, n=22, k=10 : 9 10 12 13 15 16 18 19 21 22 
s=9, n=22, k=11 : 9 10 12 13 14 16 17 18 19 21 22 
s=9, n=22, k=12 : 9 10 11 13 14 15 16 17 18 20 21 22 
s=9, n=22, k=13 : 9 10 11 12 13 14 16 17 18 19 20 21 22 
s=9, n=22, k=14 : 9 10 11 12 13 14 15 16 17 18 19 20 21 22 
s=9, n=23, k=2 : 9 23 
s=9, n=23, k=3 : 9 16 23 
s=9, n=23, k=4 : 9 14 18 23 
s=9, n=23, k=5 : 9 13 16 20 23 
s=9, n=23, k=6 : 9 12 15 17 20 23 
s=9, n=23, k=7 : 9 11 14 16 18 21 23 
s=9, n=23, k=8 : 9 11 13 15 17 19 21 23 
s=9, n=23, k=9 : 9 11 13 14 16 18 20 21 23 
s=9, n=23, k=10 : 9 11 12 14 15 17 18 20 21 23 
s=9, n=23, k=11 : 9 10 12 13 15 16 17 19 20 22 23 
s=9, n=23, k=12 : 9 10 12 13 14 15 17 18 19 20 22 23 
s=9, n=23, k=13 : 9 10 11 13 14 15 16 17 18 20 21 22 23 
s=9, n=23, k=14 : 9 10 11 12 13 14 15 17 18 19 20 21 22 23 
s=9, n=23, k=15 : 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 

答案 2 :(得分:0)

我希望得到一个十进制的集合,然后根据需要处理你的转换回到int:

        int n = 10;
        int k = 5;      // Actually 6

        List<decimal> results = new List<decimal>();

        decimal interval = (decimal)n / (decimal)k;
        for (int i = 0; i <= k ; i++)
        {
            results.Add(interval * (decimal)i);
        }

你会看到我使用k = 5来返回6的结果。

答案 3 :(得分:0)

如果允许随机长度间隔:

  1. 使用数字1到n-1
  2. 填充数组
  3. 使用例如Fisher-Yates shuffle
  4. 对阵列进行随机播放
  5. 选择第一个k-1条目并对其进行排序
  6. 前置0,追加n
  7. 这导致k + 1个随机但有序的0到n之间的值,它们定义了k个区间。使用shuffle可确保中间k-1值都是唯一的。对于shuffle,这将是O(n),对于重新排序,这将是O(k log k)。

    这是一个Ruby实现:

    def segment_line(n, k)
      raise "invalid args" if n < 1 or k < 1 or n < k
      a = Array.new(n-1).map.with_index {|x,i| i+1}
      if n > k
        a = a.shuffle[0...k-1].sort
      end
      a.unshift(0).push(n)
    end
    
    p segment_line(15, 8)      # => [0, 1, 2, 6, 10, 11, 12, 14, 15]
    p segment_line(15, 15)     # => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
    

    每次运行时都会得到不同的答案(n == k除外),但它们始终是您所述规格的有效答案。

答案 4 :(得分:0)

如果您想尽可能接近,可以执行以下操作。

q = (n+1)/k    //Integer division
r = (n+1)%k
for i = 0 to i=k
    a[i] = q*i + min(r,i)

我正在使用一个轻微的约定更改,并且间隔形成为[a [i],a [i + 1]),即左边一个闭合,右边打开,所以这是为什么a [k] = n + 1,但由于间隔是开放的,你将得到正确的结果。