以向外螺旋形式打印二维阵列

时间:2015-07-23 11:22:53

标签: arrays algorithm math

我最近在接受采访时被问到这个问题:

给定一个(N X M)数组,说:

1 2 3
4 5 6
7 8 9

打印其元素,就好像它从中心螺旋地穿过一样。 在上面的例子中,答案是

5 4 7 8 9 6 3 2 1

熟悉以向内螺旋形式打印阵列时,我建议堆叠元素并稍后弹出它们,但我被告知不要这样做。

注意:N并不总是等于M

5 个答案:

答案 0 :(得分:2)

给定NxN矩阵(N为奇数),并从中心位置[N / 2,N / 2]开始,生成螺旋的一般路径是:

move  left      1      position
move  down      1      position
move right from 1 to 2 positions
move    up from 1 to 2 positions
move  left from 1 to 3 positions
move  down from 1 to 3 positions
move right from 1 to 4 positions
move    up from 1 to 4 positions
...

您可以遵循一种模式。

在OP的问题编辑后编辑

如果矩阵是NxM且N != M或N或M是偶数,首先你必须在你的问题中澄清当你到达矩阵的一个边缘时你期望的行为:停止?继续忽略矩阵之外的位置?

答案 1 :(得分:1)

假设矩阵是N乘N且N奇数(因此它有一个中心元素),我们将使用行列调用中心元素e [n] [n]。

然后我们基本上通过绘制正方形进行打印。我会假设我们从左上角开始,因为它更容易一些。即在您的示例中,在5之后的输出中打印1。

所以打印e [n] [n],对于pe [np] [np]水平的平方,并横向遍历e [np] [n + p],然后垂直遍历e [n + p] ] [n + p]等在广场周围。当你回到e [n-p-1] [n-p]时,做p ++并重新开始直到你到达边缘。显然,你可以从一个角落开始,而不是一个角落,但它并不重要。对于N甚至你只需要适当地使用一些地板/天花板功能来处理没有中心元素的事实。

答案 2 :(得分:1)

我使用Swift 2.0来实现它,但它非常像C:

// the function returns the elements from an inward spiral which is then printed in reverse
// array has to be 2 dimensional; returns one-dimensional array of elements
func spiralElements<T>(array: [[T]]) -> [T] {
    // point which gets accessed
    var x = 0
    var y = 0

    // directions in x and y
    var dx = 1
    var dy = 0

    // bounds which get constrained further during the execution
    var xMin = 0
    var xMax = array.count - 1 // x dimension index
    var yMin = 0
    var yMax = array[0].count - 1 // y dimension index

    // a list which can be appended to
    var result = [T]()

    // loops exactly numberOfElements times of the whole array
    // x dimension count * y dimension count
    for _ in 1...(array.count * array[0].count) {
        result.append(array[x][y])

        // if future point is not inside bounds
        if !(xMin <= x + dx && x + dx <= xMax && yMin <= y + dy && y + dy <= yMax) {

            // go left
            if dy == 0 {
                dy = dx
                dx = 0
            } else {
                dx = -dy
                dy = 0
            }

            // constrain the bounds (depending on the direction)
            if dy == -1 {
                yMax--
            } else if dy == 1 {
                yMin++
            } else if dx == -1 {
                xMax--
            } else if dx == 1 {
                xMin++
            }
        }

        x += dx
        y += dy
    }

    return result
}

// calculate elements
var spiralElementsOfArray = spiralElements(...)

// printing
for var i = spiralElementsOfArray.count - 1; i >= 0; i-- {
    print(spiralElementsOfArray[i])
}

答案 3 :(得分:1)

这个天真的javascript版本将始终走标准螺旋,它将忽略越界并继续前进,直到所有元素都被访问过。

function spiral(arr, rows, cols) {
    if(rows <= 0 || cols <= 0) throw Error("Invalid Argument(s)");
    var result = [];
    var count = rows * cols;
    var col = Math.floor(cols / 2);
    var row = Math.floor(rows / 2) + ((rows & 1) == 0 ? -1 : 0);
    var vertLvl = 1;
    var horLvl = 1;
    var vertDir = 1;
    var horDir = -1;
    var i, v;
    result.push(arr[row][col]);
    count--;
    while(count > 0) {
        for(i=0; i < horLvl; i++) {
            col += horDir;
            if(row < 0 || row >= rows || col < 0 || col >= cols) { continue; }
            v = arr[row][col];
            count--; 
            result.push(v);
        }
        horDir *= -1; horLvl++;
        if(count <= 0) { break; }
        for(i=0; i < vertLvl; i++) {
            row += vertDir;
            if(row < 0 || row >= rows || col < 0 || col >= cols) { continue; }
            v = arr[row][col];
            count--; 
            result.push(v);
        }
        vertDir *= -1; vertLvl++;
        if(count <= 0) { break; }
    }
    return result;
}

console.log(spiral( [[1,2,3], [4,5,6], [7,8,9]], 3, 3 ) );
console.log(spiral( [[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]], 4, 3 ) );
console.log(spiral( [[1,2,3,4], [5,6,7,8], [9,10,11,12]], 3, 4 ) );
console.log(spiral( [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]], 4, 4 ) );

答案 4 :(得分:1)

Here是我编写的用于扫描环形图案中的点栅格的实现。您可以使用半径0,1,2等调用该函数,它将为您提供所需的索引。然后,您可以使用这些索引来访问和打印元素值。