La tarea de recorrer los elementos de una matriz bidimensional siguiendo un patrón diagonal es un problema clásico en algoritmos. El objetivo es extraer todos los elementos de la matriz en un orden específico, alternando la dirección del recorrido diagonal.
Descripción del Problema
Se proporciona una matriz (o lista de listas) de enteros. El objetivo es devolver una lista unidimensional que contenga todos los elementos de la matriz original, recorriéndolos en orden diagonal. El patrón de recorrdio es el siguiente:
- Comenzar desde el elemento superior izquierdo (
[0][0]). - La primera diagonal se recorre hacia arriba y a la derecha.
- La segunda diagonal se recorre hacia abajo y a la izquierda.
- Este patrón de alternancia (arriba-derecha, abajo-izquierda) continúa hasta que todos los elementos de la matriz han sido visitados.
Implementación en Python
A continuación, se presenta una solución en Python que aborda este problema, explicando cada parte del código para una mejor comprensión.
from typing import List
class SolucionMatricial:
def obtenerOrdenDiagonal(self, matriz: List[List[int]]) -> List[int]:
# Manejo de casos de matriz vacía o con filas vacías
if not matriz or not matriz[0]:
return []
# Obtener las dimensiones de la matriz
num_filas, num_columnas = len(matriz), len(matriz[0])
# Lista para almacenar el resultado final del recorrido
elementos_diagonales = []
# 'es_ascendente' controla la dirección del recorrido:
# True: de abajo-izquierda a arriba-derecha (fila disminuye, columna aumenta)
# False: de arriba-derecha a abajo-izquierda (fila aumenta, columna disminuye)
es_ascendente = True
# Iterar a través de todas las posibles sumas de índices (i + j = k)
# Estas sumas 'k' representan las "líneas" diagonales.
# Varían desde 0 (para el elemento [0][0]) hasta (num_filas + num_columnas - 2)
for suma_indices_k in range(num_filas + num_columnas - 1):
# Determinar los límites de los índices de columna (j) para la diagonal actual
# j debe ser al menos 0 y no exceder (num_columnas - 1)
# La fila 'i' (suma_indices_k - j) debe ser al menos 0 y no exceder (num_filas - 1)
# El índice de columna mínimo para la diagonal actual
# Asegura que i = (suma_indices_k - j) no sea mayor que (num_filas - 1)
# y que j no sea menor que 0.
limite_col_inferior = max(0, suma_indices_k - num_filas + 1)
# El índice de columna máximo para la diagonal actual
# Asegura que i = (suma_indices_k - j) no sea menor que 0
# y que j no sea mayor que (num_columnas - 1).
limite_col_superior = min(num_columnas - 1, suma_indices_k)
# Lista temporal para los elementos de la diagonal actual
temp_diagonal = []
if es_ascendente:
# Si la dirección es ascendente (arriba-derecha),
# recorrer las columnas de menor a mayor.
# Las filas disminuyen a medida que las columnas aumentan (i = k - j).
for indice_j in range(limite_col_inferior, limite_col_superior + 1):
indice_i = suma_indices_k - indice_j
temp_diagonal.append(matriz[indice_i][indice_j])
else:
# Si la dirección es descendente (abajo-izquierda),
# recorrer las columnas de mayor a menor.
# Las filas aumentan a medida que las columnas disminuyen (i = k - j).
for indice_j in range(limite_col_superior, limite_col_inferior - 1, -1):
indice_i = suma_indices_k - indice_j
temp_diagonal.append(matriz[indice_i][indice_j])
# Agregar los elementos de la diagonal actual al resultado final
elementos_diagonales.extend(temp_diagonal)
# Invertir la dirección para la siguiente diagonal
es_ascendente = not es_ascendente
return elementos_diagonales
Ejemplo Ilustrativo
Consideremos la siguiente matriz de 2x3:
matriz_ejemplo = [
[1, 2, 3],
[4, 5, 6]
]
El recorrido diagonal se desarrollaría de la sgiuiente manera:
-
Suma de índices k = 0 (
es_ascendente = True):j = 0,i = 0 - 0 = 0. Elemento:matriz[0][0]=1.
Diagonal:
[1]. Resultado:[1].es_ascendentecambia aFalse. -
Suma de índices k = 1 (
es_ascendente = False):j = 1,i = 1 - 1 = 0. Elemento:matriz[0][1]=2.j = 0,i = 1 - 0 = 1. Elemento:matriz[1][0]=4.
Diagonal:
[2, 4]. Resultado:[1, 2, 4].es_ascendentecambia aTrue. -
Suma de índices k = 2 (
es_ascendente = True):j = 1,i = 2 - 1 = 1. Elemento:matriz[1][1]=5.j = 2,i = 2 - 2 = 0. Elemento:matriz[0][2]=3.
Diagonal:
[5, 3]. Resultado:[1, 2, 4, 5, 3].es_ascendentecambia aFalse. -
Suma de índices k = 3 (
es_ascendente = False):j = 2,i = 3 - 2 = 1. Elemento:matriz[1][2]=6.
Diagonal:
[6]. Resultado:[1, 2, 4, 5, 3, 6].es_ascendentecambia aTrue.
El resultado final para este ejemplo sería: [1, 2, 4, 5, 3, 6].
Consideraciones Clave
- La propiedad fundamental de los elementos en una misma diagonal es que la suma de sus índices de fila y columna (
i + j) es constante para esa diagonal específica. - El desafío principal radica en calcular correctamente los límites de las columnas (o filas) para cada diagonal, asegurando que no se excedan los bordes de la matriz.
- La dirección del recorrido debe alternarse para cada nueva diagonal (de arriba-derecha a abajo-izquierda, y viceversa), lo cual se maneja eficazmente con un indicador booleano.