sisterAn / JavaScript-Algorithms

基础理论+JS框架应用+实践,从0到1构建整个前端算法体系

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

字节&剑指 Offer 29:顺时针打印矩阵(螺旋矩阵)

sisterAn opened this issue · comments

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

示例 1:

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]

示例 2:

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

限制:

  • 0 <= matrix.length <= 100
  • 0 <= matrix[i].length <= 100

leetcode

用四个变量up, down, left, right分别记录当前上下左右范围,每遍历一行或一列就修改相应的值。
例如遍历了上面第一行,就应该把up加一,遍历了右边第一列就应把right减一

var spiralOrder = function(matrix) {
    if (matrix === undefined || matrix.length === 0) return [];
    let res = [];
    let left = 0, right = matrix[0].length-1, up = 0, down = matrix.length-1;
    while (true) {
        for (let i = left;i <= right;i++) {
            res.push(matrix[up][i]);
        }
        if (++up > down) break;
        for (let i = up;i <= down;i++) {
            res.push(matrix[i][right]);
        }
        if (--right < left) break;
        for (let i = right;i >= left;i--) {
            res.push(matrix[down][i]);
        }
        if (--down < up) break;
        for (let i = down;i >= up;i--) {
            res.push(matrix[i][left]);
        }
        if (++left > right) break;
    }
    return res;
};

核心是四种情况的判断:

  1. 向右移动(没到右边界一直右移动遍历),到达右边界就向下移动(如果向下也是边界,说明遍历完了)
  2. 向下移动(没到下边界一直下移动遍历),到达下边界就向左移动(如果向左也是边界,说明遍历完了)
  3. 向左移动(没到左边界一直左移动遍历),到达左边界就向上移动(如果向上也是边界,说明遍历完了)
  4. 向上移动(没到上边界一直上移动遍历),到达上边界就向右移动(如果向右也是边界,说明遍历完了)
var PrintMatrixClockwise = function (matrix) {
  let border = {      // 存储边界
    top: 0,
    left: 0,
    bottom: matrix.length - 1,
    right: matrix[0].length - 1
  } 

  let direction = 'right'  // top、right、bottom、left
  let result = []
  let location = [0, 0]  // 当前坐标

  function forword() {  // 向前移动
    switch (direction) {
      case 'top':
        if (location[1] >= border['top']) {
          // 继续向前走
          result.push(matrix[location[1]][location[0]])
          location[1]--
        } else if (location[0] + 1 <= border['right']) {
          // 此方向到头了,向右
          location[0]++
          location[1]++
          direction = 'right'
          border['left']++
        } else return
        break;
      case 'right':
        if (location[0] <= border['right']) {
          // 继续向前走
          result.push(matrix[location[1]][location[0]])
          location[0]++
        } else if (location[1] + 1 <= border['bottom']) {
          // 此方向到头了,向下
          location[0]--
          location[1]++
          direction = 'bottom'
          border['top']++
        } else return
        break;
      case 'bottom':
        if (location[1] <= border['bottom']) {
          // 继续向前走
          result.push(matrix[location[1]][location[0]])
          location[1]++
        } else if (location[0] - 1 >= border['left']) {
          // 此方向到头了,向左
          location[0]--
          location[1]--
          direction = 'left'
          border['right']--
        } else return
        break;
      case 'left':
        if (location[0] >= border['left']) {
          // 继续向前走
          result.push(matrix[location[1]][location[0]])
          location[0]--
        } else if (location[1] - 1 >= border['top']) {
          // 此方向到头了,向上
          location[0]++
          location[1]--
          direction = 'top'
          border['bottom']--
        } else return
        break;
    }
    // 递归
    forword()
  }

  forword()
  return result
}
commented

一圈一圈删除

function fn(arr) {
    const res = []
    while (arr.length) {
        res.push(...arr.shift())
        if (arr.length) {
            const last = arr.pop()
            if (arr.length) {
                arr.forEach(val => {
                    res.push(val.pop())
                })
            }
            res.push(...last.reverse())
            if (arr.length) {
                const temp = []
                arr.forEach(val => {
                    temp.push(val.shift())
                })
                res.push(...temp.reverse())
            }
        }
    }
    return res
}

function echoValueClockWise(matrix) {
const temp = matrix.slice();
const result = [];

while (temp.length > 0) {
    result.push(...temp.shift());
    temp.forEach(arr => result.push(arr.pop()));
    result.push(...(temp.pop() || []).reverse());
    for (let i = temp.length - 1; i > -1; i--) {
        result.push(temp[i].shift());
    }
}

return result;

}

/**
 * @param {number[][]} matrix
 * @return {number[]}
 */
var spiralOrder = function(matrix) {
    if(matrix.length===0) {
        return []
    }
    const res = [];
    //1. 定义左边界 右边界 上边界 下边界
    let m = matrix.length;
    let n = matrix[0].length;
    let l = 0, r = n - 1, t = 0, b = m - 1;
    let matrixSize = m * n;
    while (res.length < matrixSize) {
        for (let i = l; i <= r; i++) {
            res.push(matrix[t][i]);
        }
        t++;
        for (let i = t; i <= b; i++) {
            res.push(matrix[i][r]);
        }
        r--;
        if(res.length === matrixSize) {
            break;
        }
        for (let i = r; i >= l; i--) {
            res.push(matrix[b][i]);
        }
        b--;
        for (let i = b; i >= t; i--) {
            res.push(matrix[i][l]);
        }
        l++;
    }
    return res;
};
var matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]

var queryFn = function (matrix) {
  if(matrix.length===0) return []
  let res = []
  let left = 0,
    right = matrix[0].length-1,
    top = 0,
    bottom = matrix.length-1
  let n = matrix[0].length * matrix.length
  while(true) {
    if(left>right) break
    for(let i = left; i <= right; i++) {
      res.push(matrix[top][i])
    }
    top++
    if(top>bottom) break
    for(let i=top; i <= bottom; i++) {
      res.push(matrix[i][right])
    }
    right--
    if(left>right) break
    for(let i=right; i >= left; i--) {
      res.push(matrix[bottom][i])
    }
    bottom--
    if(top>bottom) break
    for(let i=bottom; i >= top; i--) {
      res.push(matrix[i][left])
    }
    left++
  }
  return res
}

queryFn(matrix)
// [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7]