Я работаю над решением проблемы Диагональный ход - LeetCode

Учитывая матрицу из M x N элементов (M строк, N столбцов), вернуть все элементы матрицы в диагональном порядке, как показано на рисунке ниже.

Пример:

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

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

Explanation:

введите описание изображения здесь

Примечание.

Общее количество элементов данной матрицы не будет превышать 10 000.

Проблему можно рассматривать как прохождение bfs от корня (0, 0) до места назначения (строки, столбцы)

Прочитав все материалы и обсуждения, я нашел относительно лаконичное решение.

class Solution:
    def findDiagonalOrder(self, matrix: 'List[List[int]]') -> 'List[int]':
        if len(matrix) == 0:
            return []
        r, c = 0, 0
        rows, cols = len(matrix), len(matrix[0])
        res = []
        for _ in range(rows * cols):
            res.append(matrix[r][c])
            if (r + c) % 2 == 0:
                if c == cols - 1: #column boundary 
                    r += 1
                elif r == 0: # 
                    c += 1
                else: #move up 
                    r -= 1
                    c += 1
            else:
                if r == rows - 1: #row boundary 
                    c += 1
                elif c == 0:
                    r += 1
                else:#move down 
                    r += 1
                    c -= 1
        return res

У меня есть ощущение, что такое решение недостаточно хорошо, потому что слишком много трудов, чтобы использовать несколько условий проверки.

Может быть универсальное решение этой модели задач, которое можно было бы использовать позже для решения задачи обхода диагонали с минимальными усилиями.

Задача состоит в том, чтобы перейти от (0, 0) к (4, 4)

Персонажи:
1. сумма каждого узла по диагонали равна номеру шага
2. может существовать формула отношения для получения всех узлов следующего уровня из корневого (0,0) и предыдущего уровня.

enter image description here

Мое решение:

import unittest
import logging

logging.basicConfig(level=logging.DEBUG, format="%(levelname)s %(message)s")

class Solution:
    def findDiagonalOrder(self, matrix: 'List[List[int]]') -> 'List[int]':
        from collections import deque 
        #root is (0, 0)
        #destination is (rows, cols)
        r, c = 0, 0
        root = (r, c)
        rows, cols = len(matrix), len(matrix[0])  
        step = 0
        queue = deque([root]) 
        res = []

        while queue and r < rows and c < cols:
            step += 1
            size = len(queue)

            for _ in range(size):
                r, c = queue.popleft()
                res.append(matrix[r][c])

            #collect the next nodes 
            if r == 0 and c == 0: 
                c = step #(0, 1) determin the direction of the first step 
                queue.append((r,c))
                logging.debug(f"queue: {queue}")
                logging.debug(f"step: {step}, r:{r}, c: {c}")

            if c == 0:
                level = [(step-i, i) for i in range(step)]
            elif r == 0:
                level = [(i, step-i) for i in range(step)]
            queue += level 
            logging.debug(f"queue: {queue}")
            #raise Exception

        return res 

class MyCase(unittest.TestCase):
    def setUp(self):
        self.solution = Solution()

    def test_a(self):
        matrix = [
                    [ 1, 2, 3 ],
                    [ 4, 5, 6 ],
                    [ 7, 8, 9 ]
                ]
        answer = [1,2,4,7,5,3,6,8,9]
        check = self.solution.findDiagonalOrder(matrix)
        self.assertEqual(answer, check)

unittest.main()

Тем не менее, он останавливается на

DEBUG queue: deque([(0, 2), (1, 1)])
DEBUG queue: deque([(0, 2), (1, 1)])
DEBUG queue: deque([(0, 2), (1, 1)])
DEBUG queue: deque([(0, 2), (1, 1)])
^CDEBUG queue: deque([(0, 2), (1, 1)])
Traceback (most recent call last):

Мне не удалось написать хорошую формулу отношения для создания узлов на следующем уровне.

Не могли бы вы предоставить какие-либо советы?

1
Alice 19 Апр 2019 в 13:26

2 ответа

Лучший ответ

Я не уверен, что это ответит на ваш вопрос, но я могу поделиться своим подходом, если он будет достаточно кратким и понятным для вас.

Код написан на C ++, но вы можете понять это.

class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
        vector<int> result;

        int n = matrix.size();
        if(n == 0) return result;
        int m = matrix[0].size();
        if(m == 0) return result;

        result.resize(m * n);
        int row = 0, col = 0, d = 0;
        int dir[2][2] = {
               {-1, 1},
               {1, -1}
        };

        for (int i = 0; i < m * n; i++) {
            result[i] = matrix[row][col];
            row += dir[d][0];
            col += dir[d][1];

            if (row >= n) { row = n - 1; col += 2; d = 1 - d; }
            if (col >= m) { col = m - 1; row += 2; d = 1 - d; }

            if (row < 0)  { row = 0; d = 1 - d;}
            if (col < 0)  { col = 0; d = 1 - d;}
        }
        return result;
    }
};
1
Kaidul 19 Апр 2019 в 11:20

Решение пересечь квадратную матрицу

class Solution:
    def findDiagonalOrder(self, matrix: 'List[List[int]]') -> 'List[int]':
        from collections import deque 

        if(len(matrix) == 0 or len(matrix[0]) == 0):
            return []

        if(len(matrix) == 1):
            return matrix[0]

        res = []
        if(len(matrix[0]) == 1):
            for row in matrix:
                res+=row
            return res  

        r, c = 0, 0
        root = (r, c)
        rows, cols = len(matrix), len(matrix[0])  
        step = 0
        queue = deque([root]) 
        left = []
        #forwards 
        while queue and step < rows:
            step += 1
            size = len(queue)

            for _ in range(size):
                r, c = queue.popleft()
                left.append(matrix[r][c])

            if r == 0:
                level = [(i, step -i) for i in range(step+1)] #(r, c+1)
            elif c == 0:
                level = [(step-i, i) for i in range(step+1)]             
            queue += level 
            #logging.debug(f"queue: {queue}")
            #logging.debug(f"left: {left}")
            #raise Exception

        #backwords 
        step = 0
        queue = deque([root]) 
        right  = []
        #forwards 
        while queue and step < rows-1:
            step += 1
            size = len(queue)

            for _ in range(size):
                r, c = queue.popleft()
                right.append(matrix[rows-r-1][cols-c-1])

            if r == 0:
                level = [(i, step -i) for i in range(step+1)] #(r, c+1)
            elif c == 0:
                level = [(step-i, i) for i in range(step+1)]             
            queue += level 
            #logging.debug(f"queue: {queue}")
            #logging.debug(f"right: {right}")
            #raise Exception
        right.reverse()
        res = left + right 
        return res 
0
Alice 19 Апр 2019 в 13:19