【问题标题】:Any Idea or solution to this matrix challenge?对这个矩阵挑战有什么想法或解决方案吗?
【发布时间】:2020-01-16 16:13:11
【问题描述】:

您好,我是新手练习算法,我只是想知道如何解决这个螺旋矩阵挑战:

让函数 MatrixSpiral(strArr) 读取存储在 strArr 中的字符串数组,该数组将表示 2D N 矩阵,并且您的程序应在以顺时针螺旋顺序打印元素后返回元素。您应该将新形成的元素列表作为字符串返回,其中数字用逗号分隔。例如:输入:

["[4, 5, 6, 5]",   
 "[1, 1, 2, 2]",  
 "[5, 4, 2, 9]"]   

输出:

"4,5,6,5,2,9,2,4,5,1,1,2"

我以前做过简单的矩阵螺旋,但不知道如何解决这样的问题。

这不是一个简单的矩阵螺旋。我尝试使用此代码,但输出方式不同

输入是“字符串数组”的数组(见双引号),输出应该是数字用逗号分隔的字符串。

const spiralOrder = (matrix) => {

if(!matrix.length || !matrix[0].length){
        return [];
}
//Use 4 pointes to create wall around square
let rowBegin = 0,
    rowEnd = matrix.length - 1,
    colBegin = 0,
    colEnd = matrix[0].length - 1;

let result = [];
while(rowBegin <= rowEnd && colBegin <= colEnd){

    //move right
    for(let i= colBegin; i<= colEnd; i++){
            result.push(matrix[rowBegin][i]);
    }
    rowBegin++; // mark row as traversed after moving right

    //move down
    for(let i=rowBegin; i<= rowEnd; i++){
            result.push(matrix[i][colEnd]);
    }
    colEnd--; //mark column as traversed after moving down

    //move left
    if(rowBegin <= rowEnd){
            for(let i=colEnd; i >= colBegin; i--){
                    result.push(matrix[rowEnd][i]); 
            }
    }
    rowEnd--; //mark end row as traversed after moving left

    //move up
    if(colBegin <= colEnd){ 
            for(let i=rowEnd; i >= rowBegin; i--){
                    result.push(matrix[i][colBegin]);
            }
    }
    colBegin++; //mark begining column as traversed after moving up
}

return result;
};

spiralOrder([[4, 5, 6, 5], [1, 1, 2, 2], [5, 4, 2, 9]])

Output: [ '[',
  '4',
  ',',
  ' ',
  '5',
  ',',
  ' ',
  '6',
  ',',
  ' ',
  '5',
  ']',
  ']',
  ']',
  '9',
  ' ',
  ',',
  '2',
  ' ',
  ',',
  '4',
  ' ',
  ',',
  '5',
  '[',
  '[',
  '1',
  ',',
  ' ',
  '1',
  ',',
  ' ',
  '2',
  ',',
  ' ',
  '2' ]

您能分享任何解决方案吗?

【问题讨论】:

标签: javascript algorithm recursion


【解决方案1】:

一种稍微不同的方法,一种适合“递归”标签的方法,注意处理螺旋的一种好方法是取顶行,将其移除,逆时针旋转矩阵,然后重复直到完成所有行。它看起来像这样:

->  4 5 6 5  --------------+ 
    1 1 2 2  \_ rotate     |
    5 4 2 9  /          ___V___
                       [4 5 6 5]
                        -------

->  2 9  ------------------------+         
    2 2 \                        |
    1 4  +- rotate               |
    1 5 /                       _V_
                       [4 5 6 5 2 9]
                                ---

->  2 4 5  ---------------------------+  
    2 1 1  >- rotate                __V__
                       [4 5 6 5 2 9 2 4 5]  
                                    -----

->  1  -----------------------------------+
    1  \_ rotate                          |
    2  /                                  V
                       [4 5 6 5 2 9 2 4 5 1]  
                                          - 

->  1 2  ------------------------------------+
                                            _V_
                       [4 5 6 5 2 9 2 4 5 1 1 2]  
                                            ---

我们可以通过反转转置矩阵的结果来编写逆时针旋转函数。换位正在将其翻转到西北/东南对角线上。例如:

  transpose([[1, 2, 3], 
             [4, 5, 6]])

  //=>      [[1, 4],
  //         [2, 5],
  //         [3, 6]]

reversing那些行,我们得到

  //        [[3, 6],
  //         [2, 5],
  //         [1, 4]]

这是输入的逆时针旋转。

因此,涉及一些可重用函数的代码可能如下所示:

const reverse = a => 
  [...a] .reverse ();

const transpose = m => 
  m [0] .map ((c, i) => m .map (r => r [i]))

const rotate = m => 
  reverse (transpose (m))

const spiral = m => m .length < 2
  ? [... m [0]]
  : [... m [0], ... spiral (rotate (m .slice (1))) ] 

const spiralOrder = (strs) => 
  spiral (strs .map (row => JSON .parse (row)) ) .join (',')


console .log (
  spiralOrder(["[4, 5, 6, 5]",   
               "[1, 1, 2, 2]",  
               "[5, 4, 2, 9]"
  ])
)

spiralOrder 是唯一处理您有些不寻常的输入的函数。 spiraltransposerotatereverse 在普通矩阵上反向工作。 (嗯,它是 JS,所以它们在一个数组数组上工作。)

【讨论】:

  • 很好的功能解构问题^^
【解决方案2】:

您可以采用具有四个方向和一个索引对 (i/j) 的方法,以及另外四个变量来限制 upperlower 绑定的循环,以及 @987654325 @ 和 right 限制。

获取限制后,检查限制是否增加或减少。如果限制不在所需范围内,则循环结束。

最后,剩余的项被添加到结果集中。

function getSpiral(data) {
    var array = data.map(j => JSON.parse(j)),
        upper = 0,
        lower = array.length - 1,
        left = 0,
        right = array[0].length - 1,
        i = upper,
        j = left,
        result = [];

    while (true) {
        if (upper++ > lower) break;

        for (; j < right; j++) result.push(array[i][j]);
        if (right-- < left) break;

        for (; i < lower; i++) result.push(array[i][j]);
        if (lower-- < upper) break;

        for (; j > left; j--) result.push(array[i][j]);
        if (left++ > right) break;

        for (; i > upper; i--) result.push(array[i][j]);
    }
    result.push(array[i][j]);

    return result.join(',');
}

console.log(getSpiral(['[4, 5, 6, 5]', '[1, 1, 2, 2]', '[5, 4, 2, 9]']));
console.log(getSpiral(['[1, 2, 3, 4, 5]', '[6, 7, 8, 9, 10]', '[11, 12, 13, 14, 15]', '[16, 17, 18, 19, 20]']));

【讨论】:

    【解决方案3】:

    我们可以观察到对角线上发生了转弯(或多或少:)。函数f 是主要的递归处理程序,它基本上是一个 for 循环。

    function turnAndDeltas(direction){
      return {
                // dy dx
        'r': ['d', 0, 1],
        'd': ['l', 1, 0], 
        'l': ['u', 0,-1],
        'u': ['r',-1, 0]
      }[direction]
    }
    
    function isDiagonal(h, w, y, x){
      if (x >= w >> 1)
        return (y == w - x - 1) || (h - y - 1 == w - x - 1)
      else if (y > h >> 1)
        return (h - y - 1 == x)
      else
        return (y - 1 == x)
    }
     
    function f(h, w, d, y, x, count, fun){
      if (count == 0)
        return
    
      fun(y, x)
    
      let [_d, dy, dx] = turnAndDeltas(d)
    
      if (isDiagonal(h, w, y, x))
        [_, dy, dx] = turnAndDeltas(d = _d)
    
      f(h, w, d, y+dy, x+dx, count-1, fun)
    }
    
    function g(h, w, fun){
      f(h, w, 'r', 0, 0, h*w, fun)
    }
    
    var m = ["[ 1, 2, 3, 4]",
             "[10,11,12, 5]",
             "[ 9, 8, 7, 6]"]
            
    var M = m.map(x => eval(x))
    
    function fun(y, x){
      console.log(M[y][x])
    }
    
    g(M.length, M[0].length, fun)
    
    m = ["[ 1, 2, 3]",
         "[10,11, 4]",
         "[ 9,12, 5]",
         "[ 8, 7, 6]"]
         
    M = m.map(x => eval(x))
    
    g(M.length, M[0].length, fun)

    【讨论】:

      猜你喜欢
      • 2017-10-03
      • 2011-08-15
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      • 2013-12-28
      • 2015-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多