# 矩阵

# 顺时针打印矩阵 (opens new window)

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

function spiralOrder(matrix: number[][]): number[] {
  const yLength = matrix.length
  if (!yLength) {
  	return []
  }
  
  const xLength = matrix[0].length
  if (xLength === 1 || yLength === 1) {
  	return matrix.reduce((pre, cur) => pre.concat(cur), [])
  }
    
  const round = Math.ceil((xLength < yLength ? xLength : yLength) / 2)
    
  let result: number[] = []
    
  for (let i = 0; i < round; i++) {
		result.push(getCircle(xLength, yLength, i, matrix))
  }
  result = result.reduce((pre, cur) => pre.concat(cur), [])
  result.length = xLength * yLength
  return result
}


function getCircle(xLength: number, yLength: number, index: number, matrix: number[][]): number[] {
		let x = index, y = index
    xLength = xLength - index
    yLength = yLength - index
    const list: number[] = []
    while (y < xLength) {
    	list.push(matrix[x][y])
      y++
    }
    y--
    x++
    while (x < yLength) {
      list.push(matrix[x][y])
      x++
    }
    x--
    y--
    while (y >= index) {
      list.push(matrix[x][y])
      y--
    }
    y++
    x--
    while (x >= index) {
      list.push(matrix[x][y])
      x--
    }
    x++
    y++ 
		if(list.length > 1){
    	list.pop()       
		}
    return list
}

# 旋转图像 (opens new window)

给定一个 n × n 的二维矩阵表示一个图像。

将图像顺时针旋转 90 度。

function rotate(matrix: number[][]): void {
  if(!matrix.length) return 
  let left = 0
  let right = matrix.length - 1
  
  while(left < right) {
    [matrix[left], matrix[right]] = [matrix[right], matrix[left]]
    left++
    right--
  }
  
  for(let i = 0; i < matrix.length; i++) {
    for(let j = i + 1; j < matrix[i].length; j++) {
      [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]]
    }
  }
}

# 螺旋矩阵II (opens new window)

给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

function generateMatrix(n: number): number[][] {
  if(n === 1) return [[1]] // 特殊情况
  
  const res: number[][] = []
  
  for(let i = 0; i < n; i++) {
    res[i] = []
  }
  
  // 旋转圈数
  let circleNum = n - 1
  let num = 1
  // 记录循环次数,用于定义每次起点位置
  let count = 0
  
  while(circleNum) {
    let x = count
    let y = count
    
    const rect = n - count * 2
    if(rect === 1) res[y][x] = num++
    
    // 上
    for(let i = 0; i < rect - 1; i++) {
      res[y][x++] = num++
    }
    // 右
    for(let i = 0; i < rect - 1; i++) {
      res[y++][x] = num++
    }
    // 下
    for(let i = 0; i < rect - 1; i++) {
      res[y][x--] = num++
    }
    // 左
    for(let i = 0; i < rect - 1; i++) {
      res[y--][x] = num++
    }
    
    circleNum--
    count++
  }
  
  
  return res
}

# 矩阵置零 (opens new window)

给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。

// 巧用 0 === -0 且 Object.is(0, -1) === false
function setZeros(matrix: number[][]): void {
  for(let i = 0; i < matrix.length; i++) {
    for(let j = 0; j < matrix[i].length; j++) {
      if(Object.is(matrix[i][j], 0)) {
        
        for(let k = 0; k < matrix.length; k++) {
          if(k !== i && Object.is(matrix[k][j], 0)) continue
          else matrix[k][j] = -0
        }
        
        for(let k = 0; k < matrix[i].length; k++) {
          if(k !== j && Object.is(matrix[i][k], 0)) continue
          else matrix[i][k] = -0
        }
      }
    }
  }
}

标记法

function setZeros(matrix: number[][]): void {
  const rows: {[key: number]: boolean} = {}
  const cols: {[key: number]: boolean} = {}
  
  for(let i = 0; i < matrix.length; i++) {
    for(let j = 0; j < matrix[i].length; j++) {
      if(matrix[i][j] === 0) {
        rows[i] = true
        cols[j] = true
      }
    }
  }
  
  for(let i = 0; i < matrix.length; i++) {
    for(let j = 0; j < matrix[i].length; j++) {
      if(rows[i] || cols[j]) {
        matrix[i][j] = 0
      }
    }
  }
}

# 杨辉三角 (opens new window)

给定一个非负整数 *numRows,*生成杨辉三角的前 numRows 行。

img

在杨辉三角中,每个数是它左上方和右上方的数的和。

function generate(numRows: number): number[][] {
  if(numRows <= 0) return []
  
  const res: number[][] = []
  
  for(let i = 0; i < numRows; i++) {
    const subArr: number[] = []
    for(let j = 0; j <= i; j++) {
      if(j > 0 && j < i) {
        subArr.push(res[i - 1][j - 1] + res[i - 1][j])
      } else {
        subArr.push(1)
      }
    }
    res.push(subArr)
  }
  return res
}