如何递归地螺旋遍历矩阵 - javascript

时间:2016-09-28 17:17:45

标签: javascript recursion matrix

请看这个JSFiddle:https://jsfiddle.net/hc2jcx26/

我试图以螺旋方式遍历矩阵output(任意大小),以便每2秒以螺旋顺序将每个元素打印到console.log

var output = [[0, 1, 2, 3],
              [4, 5, 6, 7]];            

我期待这个输出:

0
1 //after 2 seconds delay
2 //after 2 seconds delay
3 //etc.
7
6
5
4

但我没有用上面的代码得到这个。输出遍布整个地方,甚至没有合适数量的元素。我在每次迭代后使用递归在循环中添加延迟(通过setTimeout),但我认为我没有正确设置变量。但是当我查看代码时,它对我来说很有意义。我在这里缺少什么?

4 个答案:

答案 0 :(得分:1)



var output = [[0, 1, 2, 3],
                 [4, 5, 6, 7]];

    var columns = output[0].length;
    var row;

    function spiralOrderRecursive (matrix, rowIndex) {
      rowIndex = rowIndex || 0;
      if (matrix.length) {
        row = rowIndex % 2 ? matrix[0].reverse() : matrix[0];
        row.forEach(function (item, index) {
          setTimeout(function () {
            console.log(item);
          }, (rowIndex * columns + index) * 2000);
        });
        spiralOrderRecursive (matrix.slice(1), ++rowIndex);
      }
    }
spiralOrderRecursive(output);




也是非回归



var output = [[0, 1, 2, 3, 5],
                  [6, 7, 8, 9, 10],
                  [11, 12, 13, 14, 15],
                  [16, 17, 18, 19, 20]];;
var columns = output[0].length;

function spiralOrder(output) {
      output.forEach(function (row, rowIndex) {
        row = rowIndex % 2 ? row.reverse() : row;
        row.forEach(function (item, index) {
          setTimeout(function () {
            console.log(item);
          }, (rowIndex * columns + index) * 2000);
        });
      });
    }
spiralOrder(output);




答案 1 :(得分:1)

这是我解决问题的方法。

迭代版

var matrix1 = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
    [13, 14, 15, 16]
], matrix2 = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [10, 11, 12]
], matrix3 = [
    [0, 1, 2, 3],
    [4, 5, 6, 7]
], matrix4 = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

(function (matrix) {
    var i,
        nRows = matrix.length,
        nCols = matrix[0].length,
        rowLimit = nRows - 1,
        colLimit = nCols - 1,
        rounds = 0,
        printedElements = 0,
        nElements = nRows * nCols,
        timeoutLapse = 2000;

    function print(val) {
        printedElements += 1;
        setTimeout(function () {
            console.log(val);
        }, printedElements * timeoutLapse);
    }

    do {
        for (i = rounds; i <= colLimit - rounds; i += 1) {// from left to right
            print(matrix[rounds][i]);
        }

        for (i = rounds + 1; i <= rowLimit - rounds; i += 1) {// from top to bottom
            print(matrix[i][colLimit - rounds]);
        }

        for (i = colLimit - rounds - 1; i >= rounds; i -= 1) {// from right to left
            print(matrix[rowLimit - rounds][i]);
        }

        for (i = rowLimit - rounds - 1; i >= rounds + 1; i -= 1) {// from bottom to top
            print(matrix[i][rounds]);
        }
        rounds += 1;
    } while (printedElements < nElements);

})(matrix4);

这里是fiddle(您必须打开控制台才能看到结果)。

递归版

var matrix1 = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
    [13, 14, 15, 16]
], matrix2 = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [10, 11, 12]
], matrix3 = [
    [0, 1, 2, 3],
    [4, 5, 6, 7]
], matrix4 = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

(function(matrix){
    var printedElements = 0,
        timeoutLapse = 1000;

    function print(val) {
        printedElements += 1;
        setTimeout(function () {
            console.log(val);
        }, printedElements * timeoutLapse);
    }

    function printArray(arr) {
        for(var i = 0; i < arr.length; i++) {
            print(arr[i]);
        }
    }

    // Recursive algorithm, consumes the matrix.
    function printMatrix(matrix, direction) {
        var dir = direction % 4,
            rowLimit = matrix.length - 1,
            i;

        if (dir === 0) {// from left to right
            printArray(matrix.shift());
        } else if (dir === 1) {// from top to bottom
            for(i = 0; i <= rowLimit; i++) {
                print(matrix[i].pop());
            }
        } else if (dir === 2) {// from right to left
            printArray(matrix.pop().reverse());
        } else {// from bottom to top
            for(i = rowLimit; i >= 0; i--) {
                print(matrix[i].shift());
            }
        }

        if (matrix.length) {// Guard
            printMatrix(matrix, direction + 1);
        }
    }

    // Initial call.
    printMatrix(matrix, 0);
})(matrix4);

我添加了一些示例来测试它。我只是在螺旋模式后每两秒打印一次矩阵元素。

正如您所看到的,递归版本更具说明性,尽管它完全清空了矩阵。这是fiddle

答案 2 :(得分:0)

您想要做的伪代码

spiral_print(matrix)
{ 
 If the matrix has one row
   print the row and go to new line
 else if the matrix has two rows
  print the first row and go to new line
  sleep(2)
  print the second row in reverse order and go to new line
 else
  print the first row and go to new line
  sleep(2)
  print the second row in reverse order and go to new line
  sleep(2)      
  spiral_print(matrix.slice(2))
}

答案 3 :(得分:0)

使用JS

更新:利用@ acontell的打印功能

function spiral(matrix) {
    if (matrix.length <= 0) {
        return
    }
    for (var i = 0; i < matrix[0].length; i++) {
        print(matrix[0][i])
    }

    //Get last col
    for (var i = 1; i < matrix.length; i++) {
        print(matrix[i][matrix[0].length - 1])
    }

    //Get last row
    for (var i = matrix[0].length - 2; i >= 0; i--) {
        print(matrix[matrix.length-1][i])
    }

    //Get first column
    for (var i = matrix.length - 2; i > 0; i--) {
        print(matrix[i][0])
    }
    matrix = matrix.slice(1, -1)
    for (var i = 0; i < matrix.length; i++) {
        matrix[i] = matrix[i].slice(1, -1)
    }
    spiral(matrix)
}           
function print(val) {
    printedElements += 1;
    setTimeout(function () {
        console.log(val);
    }, printedElements * 2000);
}
var printedElements = 0
matrix = [[1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
            [13, 14, 15, 16]]
matrix1 = [[1, 2, 3, 4, 31],
            [5, 6, 7, 8, 32],
            [9, 10, 11, 12, 33],
            [13, 14, 15, 16, 34],
            [35, 36, 37, 38, 39]]
spiral(matrix1)

使用Python 注意:使用numpy

会更容易
def spiral(matrix):
    if len(matrix) <= 0:
        return
    for v in matrix[0]:
        print(v)
    last_col = [matrix[i][len(matrix[0]) - 1] for i in range(1,len(matrix))]
    for v in last_col:
        print(v)
    last_row = reversed(matrix[len(matrix)-1][0:-1])
    for v in last_row:
        print(v)
    first_col = [matrix[i][0] for i in range (1, len(matrix) - 1)]
    first_col = reversed(first_col)
    for v in first_col:
        print(v)
    matrix = matrix[1:len(matrix) - 1]
    matrix = [m[1:len(matrix[0]) - 1] for m in matrix]
    spiral(matrix)
matrix = [[1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
            [13, 14, 15, 16]]
matrix1 = [[1, 2, 3, 4, 31],
            [5, 6, 7, 8, 32],
            [9, 10, 11, 12, 33],
            [13, 14, 15, 16, 34],
            [35, 36, 37, 38, 39]]

spiral(matrix1)

更新:使用numpy

import numpy as np

def spiral(matrix):
    if len(matrix) <= 0:
        return
    for v in matrix[0]:
        print(v)
    last_col = matrix[1:, -1]
    for v in last_col:
        print(v)
    last_row = reversed(matrix[-1, :-1])
    for v in last_row:
        print(v)
    first_col = reversed(matrix[1:-1, 0])
    for v in first_col:
        print(v)
    matrix = matrix[1:-1, 1:-1]
    spiral(matrix)
matrix = [[1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
            [13, 14, 15, 16]]
matrix1 = [[1, 2, 3, 4, 31],
            [5, 6, 7, 8, 32],
            [9, 10, 11, 12, 33],
            [13, 14, 15, 16, 34],
            [35, 36, 37, 38, 39]]
matrix2 = np.array([[1, 2, 3, 4, 31],
            [5, 6, 7, 8, 32],
            [9, 10, 11, 12, 33],
            [13, 14, 15, 16, 34],
            [35, 36, 37, 38, 39]])


spiral(matrix2)