[リートコード] [チュートリアル] マトリックス


73. マトリックスのゼロ化

mxn 行列の場合、要素が 0 の場合、その行と列のすべての要素を 0 に設定します。インプレースアルゴリズムを使用してください。

例:
入力: 行列 = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
出力: [[0,0,0,0], [0,4,5,0],[0,3,1,0]]

解決

この問題を解決するには、行列の最初の行と列を使用して、他の行と列を 0 に設定する必要があるかどうかを記録します。ただし、その前に、最初の行と最初の列自体を 0 に設定するかどうかを記録する 2 つのフラグ変数が必要です。

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        m = len(matrix)
        n = len(matrix[0])

        first_row_has_zero = False
        first_col_has_zero = False

        # Check if first row and first column have zero
        for i in range(m):
            if matrix[i][0] == 0:
                first_col_has_zero = True
                break

        for j in range(n):
            if matrix[0][j] == 0:
                first_row_has_zero = True
                break

        # Use first row and first column as markers
        for i in range(1, m):
            for j in range(1, n):
                if matrix[i][j] == 0:
                    matrix[i][0] = 0
                    matrix[0][j] = 0

        # Update the rest of the matrix
        for i in range(1, m):
            for j in range(1, n):
                if matrix[i][0] == 0 or matrix[0][j] == 0:
                    matrix[i][j] = 0

        # Update first row and first column
        if first_row_has_zero:
            for j in range(n):
                matrix[0][j] = 0

        if first_col_has_zero:
            for i in range(m):
                matrix[i][0] = 0

54. スパイラルマトリックス

m 行 n 列の行列が与えられた場合、行列内のすべての要素を時計回りの螺旋順序で返してください。

例:
入力: 行列 = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
出力: [1,2,3,4,8, 12,11,10,9,5,6,7]

解決

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix:
            return []

        top, bottom = 0, len(matrix) - 1
        left, right = 0, len(matrix[0]) - 1
        order = []

        while top <= bottom and left <= right:
            for i in range(left, right + 1):
                order.append(matrix[top][i])
            top += 1
            
            for i in range(top, bottom + 1):
                order.append(matrix[i][right])
            right -= 1
            
            if top <= bottom:
                for i in range(right, left - 1, -1):
                    order.append(matrix[bottom][i])
                bottom -= 1
            
            if left <= right:
                for i in range(bottom, top - 1, -1):
                    order.append(matrix[i][left])
                left += 1

        return order

上の境界を左から右にトラバースし、右の境界を上から下にトラバースする場合、毎回上と右を更新するため、トラバースが繰り返されないことを保証できます。これは、両方の走査を無条件に実行できることを意味します。

下の境界を右から左にトラバースし、左の境界を下から上にトラバースする場合、上部と右側はトラバース前に更新されているため、何かが残っているかどうかを判断するために、上 <= 下、および左 <= 右であるかどうかを確認する必要があります。行または列を走査する必要があります。上 > 下、または左 > 右の場合、その行または列は前の走査で走査されているため、再度走査することはできないことを意味します。

48. 画像を回転する

画像を表す n × n の 2 次元行列行列が与えられます。画像を時計回りに90度回転してください。

例:
入力: 行列 = [[1,2,3],[4,5,6],[7,8,9]]
出力: [[7,4,1],[8,5,2], [9,6,3]]

解決

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        n = len(matrix)
        # 对角线翻转
        for i in range(n):
            for j in range(i, n):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
        # x轴翻转
        for i in range(n):
            matrix[i] = matrix[i][::-1]

または

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        n = len(matrix)

        for i in range(0, n):
            for j in range(0, n - i):
                matrix[i][j], matrix[n - 1 - j][n - 1 - i] = matrix[n - 1 - j][n - 1 - i], matrix[i][j]

        for j in range(0, n):
            for i in range(0, (n - 1) // 2 + 1):
                matrix[i][j], matrix[n - 1 - i][j] = matrix[n - 1 - i][j], matrix[i][j]

画像を時計回りに 90 度回転する問題を解決するもう 1 つの方法は、4 要素のリングを置き換えることです。

  • 2 つのレベル ループを定義します。外側のループ i は、最外層から開始して行列の中心に向かう現在の処理レベルを表します。内側のループ j は、現在のレベルでのループ置換の開始点を表し、その終了点で終了します。現在のレベル。
  • 各層で、4 要素のループ置換が実行されます。つまり、左上隅の要素が右上隅に移動され、右上隅の要素が右下隅に移動され、右下隅の要素は左下隅に移動し、左下隅の要素は左上隅に移動します。
class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        n = len(matrix)
        for i in range(n // 2):
            for j in range((n + 1) // 2):
                matrix[i][j], matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1] = matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1], matrix[i][j]

240. 二次元行列の探索 II

mxn 行列でターゲット値 target を検索する効率的なアルゴリズムを作成します。この行列の各行の要素は左から右に昇順に配置され、各列の要素は上から下に昇順に配置されます。

例:
入力: 行列 = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14, 17,24],[18,21,23,26,30]]、ターゲット = 5
出力: true

解決

それは、各行が左から右に昇順であり、各列が上から下に昇順であるというだけです。行全体の要素が必ずしも順序付けされているわけではないため、行列全体を並べ替えられたリストとして扱い、通常の二分探索を行うことはできません。

ただし、行ごとに二分探索を使用して、ターゲットが行内にあるかどうかを判断し、ターゲットが表示されるかどうかを判断できます。

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        for row in matrix:
            idx = bisect.bisect_left(row, target)
            if idx < len(row) and row[idx] == target:
                return True
        return False

bisect は、順序付きリストの二分探索機能を提供する組み込みモジュールです。bisect モジュールには次の主な機能が含まれています。

bisect_left(list, num, beg, end): この関数は、リストの順序を維持するために、順序付きリスト内の数値 num の挿入ポイントを見つけるために使用されます。num がリストにすでに存在する場合、挿入ポイントは既存の要素の前 (つまり、左側) にあります。beg パラメータと end パラメータのデフォルトは 0 と len(list) ですが、指定された範囲に設定できます。

行列の右上隅または左下隅の要素に注目すると、興味深いパターンが見つかります。右上隅から始めます:

  • ターゲット値がこの要素より小さい場合、この列を除外できます。これは、この列のすべての要素が右上隅の要素より大きいため (昇順であるため)、これらの要素は確実に要素より大きいためです。目標値。
  • ターゲット値がこの要素より大きい場合は、この行を除外できます。これは、この行のすべての要素が右上の要素よりも小さいため (昇順であるため)、ターゲット値よりも確実に小さいためです。
  • ターゲット値がこの要素と等しい場合、ターゲット値が見つかったことになります。

同様のパターンが左下隅からも見られます。このようにして、ターゲット値と現在の要素の比較に基づいて、行または列を除外するかどうかを決定できます。

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        m, n = len(matrix), len(matrix[0])
        i, j = 0, n - 1
        while i < m and j >= 0:
            if matrix[i][j] == target:
                return True
            elif matrix[i][j] < target:
                i += 1
            else:
                j -= 1
        return False

おすすめ

転載: blog.csdn.net/weixin_45427144/article/details/131424930