矩阵
73. 矩阵置零
原地置零的方法是:
- 首先记录首行首列是否存在0。
- 对于非首行非首列的每个元素,如果其值=0,则令该行行首和该列列首元素=0,用于标识“这一行/列应当被归零”。
- 遍历非首行非首列的所有元素,如果发现该元素所在的行首或列首元素=0,说明这个元素所在的行和列应当被全部归零,则令该元素=0.
- 最后再根据之前记录的首行或首列是否存在0元素的情况,把首行或首列置零。
class Solution {
public void setZeroes(int[][] matrix) {
if (matrix.length == 0)
return;
int row = matrix.length;
int col = matrix[0].length;
int is_first_row_contains_zero = 0, is_first_column_contains_zero = 0;
for (int i = 0; i < row; i++) {
if (matrix[i][0] == 0) {
is_first_column_contains_zero = 1;
break;
}
}
for (int i = 0; i < col; i++) {
if (matrix[0][i] == 0) {
is_first_row_contains_zero = 1;
break;
}
}
for (int i = 1; i < row; i++) {
for (int j = 1; j < col; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
for (int i = 1; i < row; i++) {
for (int j = 1; j < col; j++) {
if (matrix[i][0] == 0 || matrix[0][j] == 0)
matrix[i][j] = 0;
}
}
if (is_first_column_contains_zero == 1) {
for (int i = 0; i < row; i++)
matrix[i][0] = 0;
}
if (is_first_row_contains_zero == 1) {
for (int i = 0; i < col; i++)
matrix[0][i] = 0;
}
}
}
54. 螺旋矩阵
我自己想的方法:矩阵元素全都>=-100对吧,所以我给遍历过的矩阵元素设置值=-101.
每次遍历指针朝着右/下/左/上的一个方向遍历,如果数组越界,或者碰到=-101的元素(说明碰到之前遍历过的元素了)则切换到下一个方向。
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
if (matrix.length == 0)
return null;
int[] directions = new int[] { 0, 1, 1, 0, 0, -1, -1, 0 };
int current_direction = 0, p_x = 0, p_y = 0;
int num = matrix.length * matrix[0].length;
List<Integer> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
list.add(matrix[p_x][p_y]);
matrix[p_x][p_y] = -101;
if (p_x + directions[current_direction] < 0 || p_x + directions[current_direction] >= matrix.length
|| p_y + directions[current_direction + 1] < 0
|| p_y + directions[current_direction + 1] >= matrix[0].length
|| matrix[p_x + directions[current_direction]][p_y + directions[current_direction + 1]] <= -101) {
current_direction = (current_direction + 2) % 8;
}
p_x += directions[current_direction];
p_y += directions[current_direction + 1];
}
return list;
}
}
方向向量的方法是之前写吃豆人的时候悟出来的哈哈,用 [0,1] [1,0] [0,-1] [-1,0] 分别代表四个方向。
48. 旋转图像
这道题我还记得上次的做法:先对角翻转,再水平翻转。
class Solution {
public void rotate(int[][] matrix) {
for (int i = 0; i < matrix.length; i++) {
for (int j = i + 1; j < matrix.length; j++)
swap(matrix, i, j, j, i);
}
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix.length / 2; j++) {
swap(matrix, i, j, i, matrix.length - 1 - j);
}
}
}
public void swap(int[][] matrix, int i, int j, int a, int b) {
int temp = matrix[i][j];
matrix[i][j] = matrix[a][b];
matrix[a][b] = temp;
}
}
240. 搜索二维矩阵 II
答案中比较优秀的一种做法是 z 字形遍历。
首先,我们想象一下:如果一个点作为一个矩阵最右下角的点,那么所有比他小的点都在他左上方的矩阵里。其他部分的元素,右侧也好下侧也好,都只会比他大。
我们假设这个点一开始位于整个矩阵的右上角。那么它作为子矩阵的右下角元素,涵盖的比他小的子矩阵就只有第一行。
接着,如果我们要找的目标元素比这个元素大,说明目标元素不在这个元素的左上角子矩阵里,我们令这个元素往下移动(让 [x, y+1] 位置的元素作为新的子矩阵右下角元素),一点点向下移动扩大范围。
如果我们要找的目标元素比这个元素小,说明这个元素在子矩阵中,我们令这个元素向左移动(让 [x-1, y] 位置的元素作为新的子矩阵右下角元素),缩小子矩阵范围。
这样z字形遍历,可以有效锁定目标元素的位置。反之,如果遍历元素越界了,说明矩阵中不存在目标元素,return false.
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int x = 0, y = matrix[0].length - 1;
while (x < matrix.length && y >= 0) {
if (matrix[x][y] == target)
return true;
else if (matrix[x][y] < target)
x++;
else
y--;
}
return false;
}
}