从循环索引k获得对i,j,其中i <1。 J&prime;

时间:2014-09-30 19:58:36

标签: algorithm loops matrix mapping integer-arithmetic

对于某些正整数i,j,我需要使用0 <= i < n0 <= j < ni < j遍历所有对n

问题是我只能循环遍历另一个变量,比如k。我可以控制k的界限。所以问题是要确定两个算术方法f(k)g(k),以便i=f(k)j=g(k)遍历所有可接受的对,因为k遍历其连续值。< / p>

我怎样才能以简单的方式做到这一点?

5 个答案:

答案 0 :(得分:3)

我想我得到了它(在Python中):

def get_ij(n, k):
  j = k // (n - 1)  # // is integer (truncating) division
  i = k - j * (n - 1)
  if i >= j:
    i = (n - 2) - i
    j = (n - 1) - j
  return i, j

for n in range(2, 6):
  print n, sorted(get_ij(n, k) for k in range(n * (n - 1) / 2))

它基本上折叠矩阵,使其(几乎)呈矩形。几乎&#34;几乎&#34;我的意思是在最底行的最右边可能有一些未使用的条目。

以下图片说明折叠如何适用于n = 4:

n=4

和n = 5:

n=5

现在,迭代矩形很容易,就像从折叠坐标映射回原始三角矩阵中的坐标一样。

优点:使用简单的整数数学。

缺点:以奇怪的顺序返回元组。

答案 1 :(得分:3)

我认为我发现了另一种方式,它以字典顺序给出对。请注意,i > j代替i < j

基本上算法由两个表达式组成:

i = floor((1 + sqrt(1 + 8*k))/2)
j = k - i*(i - 1)/2

i,j作为k的函数。这里k是一个从零开始的索引。

优点:以字典顺序给出对。

缺点:依赖于浮点运算。

<强>理由:

我们希望在下表中实现映射:

k -> (i,j)
0 -> (1,0)
1 -> (2,0)
2 -> (2,1)
3 -> (3,0)
4 -> (3,1)
5 -> (3,2)
....

我们首先考虑逆映射(i,j) -> k。要意识到这一点并不难:

k = i*(i-1)/2 + j

j < i以来,k对应于具有固定(i,j)的所有对i的值满足:

i*(i-1)/2 <= k < i*(i+1)/2

因此,给定ki=f(k)会返回i这样的最大整数i*(i-1)/2 <= k。经过一些代数:

i = f(k) = floor((1 + sqrt(1 + 8*k))/2)

我们找到值i后,j可以通过

轻易给出
j = k - i*(i-1)/2

答案 2 :(得分:0)

我不确定完全理解这个问题,但总结一下,如果0&lt; = i&lt; n,0&lt; = j&lt; n,那么你想要遍历0&lt; = k&lt; N * N

for (int k = 0; k < n*n; k++) {
    int i = k / n;
    int j = k % n;
    // ...
}

[编辑]我刚看到我&lt; j;所以,这个解决方案不是最优的,因为n * n必要的迭代次数就少了......

答案 3 :(得分:0)

如果我们根据数字三角形来考虑我们的解决方案,其中k是序列

1 
2  3 
4  5  6 
7  8  9  10
11 12 13 14 15
...   

然后j将是我们的(非零基础)行号,即最大整数,

j * (j - 1) / 2 < k
j

Solving

j = ceiling ((sqrt (1 + 8 * k) - 1) / 2)

i行中k&#39; s(从零开始)的位置

i = k - j * (j - 1) / 2 - 1

k的界限是:

1 <= k <= n * (n - 1) / 2 

答案 4 :(得分:0)

您实际上有两个算术函数f(k)和g(k)这样做很重要吗?因为您可以先创建一个列表,例如

L = []
for i in range(n-1):
    for j in range(n):
        if j>i:
            L.append((i,j))

这将为您提供所有您需要的对。您的变量k现在可以沿着列表的索引运行。例如,如果我们取n = 5,

for x in L:
    print(x)

给我们

(0,1), (0,2), (0,3), (0,4), (1,2), (1,3), (1,4), (2,3), (2,4), (3,4)

例如,假设您有2 <= k <5,则

for k in range(2, 5)
    print L[k]

收益

(0,3), (0,4), (1,2)