程式設計師面試金典-1.8 零矩陣。編寫一種演算法,若 M ×N 矩陣中某個元素為 0,則將其所在的行與列清零。
阿新 • • 發佈:2021-11-04
解法一:
思想:計下每一個0元素的行列,放在集合中,然後集合轉陣列,(直接放陣列也行,感覺自己有點多餘,原本想減少陣列例項的記憶體,但是也增加了物件。得不償失吧,兩者的空間複製度都是一樣);然後更具對應的陣列的行列,將其變為0
public class SetZeroTest { public static void main(String[] args) { int[][] matrix = {{1, 2, 3, 4}, {5, 0, 7, 8}, {9, 10, 11, 12, 0}, {13, 14, 15, 16, 5}}; System.out.println("修改前陣列:"); for (int i = 0; i < matrix.length; i++) { System.out.println(Arrays.toString(matrix[i])); } setZero(matrix); System.out.println("修改後陣列:"); for (int i = 0; i < matrix.length; i++) { System.out.println(Arrays.toString(matrix[i])); } } static void setZero(int[][] matrix) { Set<Integer> rows = new HashSet<>(); Set<Integer> columns = new HashSet<>(); // 把每一個0元素的行列索引儲存起來 for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { if (matrix[i][j] == 0) { rows.add(i); columns.add(j); } } } Object[] rowsArray = rows.toArray(); Object[] columnsArray = columns.toArray(); int temp; // 把rows中對應的行都設定成空行 for (int i = 0; i < rowsArray.length; i++) { temp = (int)rowsArray[i]; for (int j = 0; j < matrix[temp].length; j++) { matrix[(int)rowsArray[i]][j] = 0; } } // 把columns中對應的行都設定成空列 for (int i = 0; i < columnsArray.length; i++) { for (int j = 0; j < matrix.length; j++) { temp = (int)columnsArray[i]; System.out.println(j + "temp = " + temp); if (matrix[j].length - 1 < temp ) { continue; } matrix[j][temp] = 0; } } } }
通過書籍學習到的進階方法:
思想:為了提高空間利用率,可以選用位向量替代布林陣列。儲存空間的複雜度仍然為 O(N)。通過使用第一行替代 row 陣列,第一列替代 column 陣列,可以將演算法的空間複雜度降為O(1),其具體步驟如下。
- (1) 檢查第一行和第一列是否存在 0 元素,並根據結果設定 rowHasZero 和 columnHasZero
的值(如果需要的話,稍後會將第一行和第一列清零)。 - (2) 遍歷矩陣中的其餘元素,如果 matrix[i][j]為 0,則將 matrix[i][0]和 matrix[0][j]置為 0。
- (3) 遍歷矩陣中的其餘元素,如果 matrix[i][0]為 0,則將第 i 行清零。
- (4) 遍歷矩陣中的其餘元素,如果 matrix[0][j]為 0,則將第 j 行清零。
-(5) 根據第(1)步的結果,如果需要則將第一行和第一列清零。
void newSetZeros(int[][] matrix) { boolean rowHasZero = false; boolean columnHasZero = false; // 檢測第一行是否有0 for (int j = 0; j < matrix[0].length; j++) { if (matrix[0][j] == 0) { rowHasZero = true; break; } } //檢測第一列是否有0 for (int i = 0; i < matrix.length; i++){ if (matrix[i][0] == 0) { columnHasZero = true; break; } } // 檢測陣列其餘元素是否有0 for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { if (matrix[i][j] == 0) { matrix[i][0] = 0; matrix[0][j] = 0; } } } // 根據第一列的值置空行 for (int i = 1; i < matrix.length; i++) { if (matrix[i][0] == 0) { nullifyRow(matrix, i); } } // 根據第一行的值置空列 for (int j = 0; j < matrix[0].length; j++) { if (matrix[0][j]== 0) { nullifyColumn(matrix, j); } } // 置空第一行 if (rowHasZero) { nullifyRow(matrix, 0); } // 指控第一列 if (columnHasZero) { nullifyColumn(matrix, 0); } } private void nullifyColumn(int[][] matrix, int column) { for (int i = 0; i < matrix.length; i++) { matrix[i][column] = 0; } } private void nullifyRow(int[][] matrix, int row) { for (int j = 0; j < matrix[0].length; j++) { matrix[row][j] = 0; } } }