1. 程式人生 > >LeetCode[in-place]----Set Matrix Zeroes

LeetCode[in-place]----Set Matrix Zeroes

Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place.

Example 1:

Input: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
Output: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

Example 2:

Input: 
[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]
Output: 
[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]

Follow up:

  • A straight forward solution using O(mn) space is probably a bad idea.
  • A simple improvement uses O(m + n) space, but still not the best solution.
  • Could you devise a constant space solution?

分析:

將一個m*n的矩陣中0元素所在的行和列均置為0,用原地演算法。用原地演算法意味著不能借助與m、n相關的陣列空間。看到題後能直接想到一個非原地演算法,即記錄應該置0的行及列,遍歷完成後再將這些行和列置零,但是需要最多m+n個空間。

但是如何用原地的方法呢?用原地的方法意味著我們不能借助額外的空間去記錄哪一行哪一列應該置為0,我開始考慮位移運算、考慮是否可以移動(swap)矩陣元素、考慮是否能遞迴在遞迴結束後開始置零操作,但是都失敗了。後來想到這種行和列的置零操作就類似於一個矩形的多米樂骨牌,又由倒下的多米樂骨牌與站立的骨牌樣式不一樣想到,我可以將應該置零的行或列先做個標記,每遇到一個應該置0的行,我將該行中每個非0的元素均置為特殊字元x,在遍歷結束後,將矩陣所有的x都設定為0,這樣即解決了所有0元素所在行和列均置0的操作。

實踐中可以將特殊字元x設定為矩陣所有元素不包含的元素,如x為矩陣中最大的元素 + 1,而在Python中,我可以將x設定為字元。

程式碼:

    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        row_num, col_num = len(matrix), len(matrix[0])
        for r in range(row_num):
            for c in range(col_num):
                if matrix[r][c] == 0:
                    self.setRowFlags(matrix, col_num, r)
                    self.setColFlags(matrix, row_num, c)

        for r in range(row_num):
            for c in range(col_num):
                if matrix[r][c] == 'f':
                    matrix[r][c] = 0

    def setRowFlags(self, matrix, col_num, row):
        for i in range(col_num):
            if matrix[row][i] != 0:
                matrix[row][i] = 'f'

    def setColFlags(self, matrix, row_num, col):
        for i in range(row_num):
            if matrix[i][col] != 0:
                matrix[i][col] = 'f'

晚上更新:

提交後看到了一種更好的解題思路:遍歷矩陣元素,如果元素為0,則將矩陣的第一行和第一列的對應位置元素設為0,作為之後置零的標記,再通過一個額外的變數記錄第一行和第一列是否要置零。

程式碼如下:

    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: void Do not return anything, modify matrix in-place instead.
        """
        row_num, col_num = len(matrix), len(matrix[0])
        update_first_row, update_first_col = False, False
        for r in range(row_num):
            for c in range(col_num):
                if matrix[r][c] == 0:
                    matrix[r][0] = 0
                    matrix[0][c] = 0
                    if r == 0:
                        update_first_row = True
                    if c == 0:
                        update_first_col = True

        for r in range(1, row_num):  # update start from second row
            if matrix[r][0] == 0:
                for i in range(col_num):
                    matrix[r][i] = 0

        for c in range(1, col_num):  # update start from second column
            if matrix[0][c] == 0:
                for i in range(row_num):
                    matrix[i][c] = 0

        if update_first_row:
            for i in range(col_num):
                matrix[0][i] = 0

        if update_first_col:
            for i in range(row_num):
                matrix[i][0] = 0