Pular para o conteudo principal

Matriz espiral

Como percorrer uma matriz em camadas usando limites claros em vez de depender de condições espalhadas.

Dada uma matriz matrix, retorne todos os elementos em ordem espiral.

Exemplo:

Input:
  matrix = [
    [1,2,3],
    [4,5,6],
    [7,8,9]
  ]

Output: [1,2,3,6,9,8,7,4,5]

O que perceber antes de codar

Erros comuns

Passo 1 - Entender o percurso por camadas

A ordem espiral não e aleatoria.

Ela percorre:

  • a borda de fora
  • depois a proxima borda interna
  • e assim por diante

Isso e um percurso por camadas.

Passo 2 - Escrever a versão inicial mais direta

A versão inicial natural e:

  • manter direção atual
  • manter matriz de visitados
  • virar quando bater em limite ou celula já vista

Funciona.

Mas pede mais estado do que o necessário.

Passo 3 - Perguntar qual estado realmente importa

Para a camada atual, basta saber:

  • top
  • bottom
  • left
  • right

Esses quatro limites dizem exatamente o retangulo ainda não percorrido.

Passo 4 - Percorrer e encolher

Em cada rodada:

  • percorra o topo
  • percorra a direita
  • se ainda existir linha sobrando, percorra o fundo
  • se ainda existir coluna sobrando, percorra a esquerda

Depois encolha os limites.

O editor interativo precisa de JavaScript. Voce ainda pode ler o desafio e copiar o codigo inicial abaixo.

Codigo inicial

export function spiralOrder(matrix: number[][]): number[] {
  // sua solução aqui
  return []
}
solution.ts
Travado? Dicas disponiveis.

Ainda não resolveu?

Ver a solução agora pode reduzir o aprendizado. Vale a pena tentar mais um pouco.

Abrir a solucao de referencia

Sem JavaScript, a solucao de referencia aparece inline em vez de um dialogo.

Solução

Complexidade final

Tempo: O(m * n)

Espaço: O(1)

Solução 1 - Simulação com visitados

Boa versão inicial porque deixa o percurso explícito.

export function spiralOrder(matrix: number[][]): number[] {
  const rows = matrix.length
  const cols = matrix[0].length
  const visited = Array.from({ length: rows }, () => new Array(cols).fill(false))
  const result: number[] = []
  const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
  let directionIndex = 0
  let row = 0
  let col = 0

  for (let count = 0; count < rows * cols; count += 1) {
    result.push(matrix[row][col])
    visited[row][col] = true

    const nextRow = row + directions[directionIndex][0]
    const nextCol = col + directions[directionIndex][1]
    const outOfBounds = nextRow < 0 || nextRow >= rows || nextCol < 0 || nextCol >= cols

    if (outOfBounds || visited[nextRow][nextCol]) {
      directionIndex = (directionIndex + 1) % 4
    }

    row += directions[directionIndex][0]
    col += directions[directionIndex][1]
  }

  return result
}

Funciona, mas existe um modelo mais limpo para esse tipo de percurso.

Solução 2 - Quatro limites

Agora você percorre a camada atual e encolhe o retangulo restante.

export function spiralOrder(matrix: number[][]): number[] {
  const result: number[] = []
  let top = 0
  let bottom = matrix.length - 1
  let left = 0
  let right = matrix[0].length - 1

  while (top <= bottom && left <= right) {
    for (let col = left; col <= right; col += 1) {
      result.push(matrix[top][col])
    }
    top += 1

    for (let row = top; row <= bottom; row += 1) {
      result.push(matrix[row][right])
    }
    right -= 1

    if (top <= bottom) {
      for (let col = right; col >= left; col -= 1) {
        result.push(matrix[bottom][col])
      }
      bottom -= 1
    }

    if (left <= right) {
      for (let row = bottom; row >= top; row -= 1) {
        result.push(matrix[row][left])
      }
      left += 1
    }
  }

  return result
}

O insight forte aqui e usar os limites como representação do problema restante.

O que dizer na entrevista

Uma explicação curta e boa seria:

A versão inicial usa direção atual mais matriz de visitados, mas isso carrega estado demais. A versão forte representa a camada atual com quatro limites: top, bottom, left e right. Eu percorro as quatro bordas que ainda existem e depois encolho esses limites, mantendo só estado extra O(1).

Isso mostra que você:

  • simplificou o estado
  • pensou em camadas, não em movimento solto
  • cuidou dos casos de borda de linha e coluna restante

Quando esse padrão aparece de novo

Esse padrão reaparece quando você precisa:

  • percorrer matriz por camadas
  • manter limites claros
  • fazer simulação com estado mínimo

O ponto não e decorar esse problema.

O ponto e aprender a modelar o que ainda falta percorrer.

Proximo desafio Serializar e desserializar árvore binária Desafio anterior Maior subsequência comum

Desafios relacionados

Artigos relacionados