我正在构建类似热图的矩形阵列接口,并且希望“热”位置在阵列的左上方,而“冷”位置在阵列的右下方。因此,我需要像这样对角填充一个数组:
0 1 2 3 |----|----|----|----| 0 | 0 | 2 | 5 | 8 | |----|----|----|----| 1 | 1 | 4 | 7 | 10 | |----|----|----|----| 2 | 3 | 6 | 9 | 11 | |----|----|----|----|
所以实际上,我需要一个函数f(x,y)这样
f(0,0) = 0 f(2,1) = 7 f(1,2) = 6 f(3,2) = 11
(或者,当然是类似的函数f(n),其中f(7)= 10,f(9)= 6,等等)。
有趣的问题是,如果您只能逐行遍历数组。我将矩形分为三个区域。在 左上部的三角形状 ,在 底部直角三角形 和 中间菱形 。
对于 左上三角形 ,可以使用通用算术级数计算第一列(x = 0)中的值1 + 2 + 3 + .. + n = n*(n+1)/2。该三角形中具有相同x + y值的字段在同一对角线中,并且该值是第一个列+ x的和。
1 + 2 + 3 + .. + n = n*(n+1)/2
相同的方法适用于 右下三角形 。但是,而不是x和y,w-x并且h-y被使用,其中,w为宽度和h矩形的高度。该值必须从w*h-1数组中的最大值中减去。
x
y
w-x
h-y
w
h
w*h-1
中间 的 菱形 有两种情况。如果矩形的宽度大于(或等于)高度,则矩形的左下角字段是菱形中值最低的字段,可以从之前的总和中计算出h-1。从那里开始,您可以想象菱形是一个矩形,其x值为x x+y,y值为y原始矩形。因此,计算该 新矩形 中的剩余值很容易。 在另一种情况下,当高度大于宽度时,则可以使用该算术和求和处的场,x=w-1并且y=0菱形可以想象为具有x值x和y值的矩形y-(w-x-1)。
h-1
x+y
x=w-1
y=0
y-(w-x-1)
例如,可以通过预先计算值来优化代码。我认为对于所有这些情况也有一个公式。也许以后再考虑。
inline static int diagonalvalue(int x, int y, int w, int h) { if (h > x+y+1 && w > x+y+1) { // top/left triangle return ((x+y)*(x+y+1)/2) + x; } else if (y+x >= h && y+x >= w) { // bottom/right triangle return w*h - (((w-x-1)+(h-y-1))*((w-x-1)+(h-y-1)+1)/2) - (w-x-1) - 1; } // rhomboid in the middle if (w >= h) { return (h*(h+1)/2) + ((x+y+1)-h)*h - y - 1; } return (w*(w+1)/2) + ((x+y)-w)*w + x; }
for (y=0; y<h; y++) { for (x=0; x<w; x++) { array[x][y] = diagonalvalue(x,y,w,h); } }
当然,如果没有这样的限制,类似的东西应该会更快一些:
n = w*h; x = 0; y = 0; for (i=0; i<n; i++) { array[x][y] = i; if (y <= 0 || x+1 >= w) { y = x+y+1; if (y >= h) { x = (y-h)+1; y -= x; } else { x = 0; } } else { x++; y--; } }