二维数组变换

/*566、重塑矩阵*/
/*思路一:
* 判断如果给定的大小与要求不相等说明不能构建等大的数组直接返回原数组
* 创建要求的数组,遍历原数组的同时遍历新数组,填入元素
* */
public int[][] matrixReshape(int[][] mat, int r, int c) {
int m = mat.length, n = mat[0].length;
if (m * n != r * c) return mat;
int[][] res = new int[r][c];
int x = 0, y = 0;
for (int[] ints : mat) {
for (int j = 0; j < n; j++) {
res[x][y] = ints[j];
if (y == c - 1) {
y = 0;
x += 1;
} else {
y++;
}
}
}
return res;
}

/*73、矩阵置零*/
/*思路一:
核心思想:用第一行和第一列标记该行或该列是否需要改0,如果某个元素是0,那么所在行和所在列第一个位置都应置零
但是如果只是这样做一定会造成连锁反应,导致所有数错误判断
所以我们先不判断第一行第一列,将其余元素判断后在对应第一行第一列标记,然后依次判断标记后在对应行或列将元素全部改为0
那么剩下第一行和第一列怎么办,如果两个都遍历,然后如果有0就再遍历一次改为0,那么第一个元素不好解决,因为你不知道第一个本来就是0还是改为了0
所以要在所有步骤前面先判断第一行或第一列是否有0,用两个布尔变量记录下来,然后最后再根据布尔变量修改元素
代码虽然繁琐,却真正实现了0额外空间
* */
/*通过*/
public void setZeroes(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
boolean r = false;
boolean c = false;
for (int[] ints : matrix) {
if (ints[0] == 0) {
c = true;
break;
}
}
for (int i = 0; i < n; i++) {
if (matrix[0][i] == 0) {
r = true;
break;
}
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
for (int i = 1; i < m; i++) {
if (matrix[i][0] == 0) {
for (int j = 0; j < n; j++) {
matrix[i][j] = 0;
}
}
}
for (int i = 1; i < n; i++) {
if (matrix[0][i] == 0) {
for (int j = 0; j < m; j++) {
matrix[j][i] = 0;
}
}
}
if (r) {
for (int i = 0; i < n; i++) {
matrix[0][i] = 0;
}
}
if (c) {
for (int i = 0; i < m; i++) {
matrix[i][0] = 0;
}
}

}

/*48、旋转图像*/
/*思路一:先镜像反转,在按照斜对角线反转
* 斜对角线反转:与当前元素对应的元素是:行=总列-当前列,列=总行-当前行
* */
/*通过*/
public void rotate(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n / 2; j++) {
int tmp = matrix[i][j];
matrix[i][j] = matrix[i][n - 1 - j];
matrix[i][n - j - 1] = tmp;
}
}
int k = n;
for (int i = 0; i < m; i++) {
for (int j = 0; j < k; j++) {
int r = n - j - 1;
int c = m - i - 1;
int tmp = matrix[i][j];
matrix[i][j] = matrix[r][c];
matrix[r][c] = tmp;
}
k--;
}
}

/*289、生命游戏*/
/*思路一:
* 原地模拟,
* 先遍历一遍数组,我们用正数来表示当前细胞是存活状态并且周围八个细胞的存活个数,
* 用负数来表示当前细胞是死亡状态并且周围八个细胞的存活个数
* 然后再次遍历数组,判断
* 如果是正数
* 小于2,则置为0宣判死亡
* 等于2或3,置为1依然存活
* 大于3,宣判死亡
* 如果是负数
* 等于三,置为1复活
* 否则置为0长眠
*
* */
/*注意:当当前周围一个活的都没有并且当前是活的,那之后当前细胞会死亡,但是在代码中会将周围活细胞个数也就是0赋给当前细胞,导致往后的元素会判断到当前为死细胞
* 怎么避免这个问题:如果出现这种情况,可以将当前细胞设置为1,这样往后的细胞会知晓这个细胞是活的,但最后判断时又会将此细胞扼杀因为会一位当前细胞是活的但周围只有一个活的*/
/*通过*/
public void gameOfLife(int[][] board) {
int m = board.length, n = board[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int cnt = 0;
for (int k = i - 1; k <= i + 1; k++) {
for (int l = j - 1; l <= j + 1; l++) {
if (k == i && l == j) continue;
if (k >= 0 && k < m && l >= 0 && l < n && board[k][l] > 0) {
cnt++;
}
}
}
if (cnt == 0 && board[i][j] == 1) {
continue;
}
board[i][j] = board[i][j] == 1 ? cnt : -cnt;
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int val = board[i][j];
if (val > 0) {
if (val == 2 || val == 3) {
board[i][j] = 1;
} else {
board[i][j] = 0;
}
} else {
if (val == -3) {
board[i][j] = 1;
} else {
board[i][j] = 0;
}
}
}
}
}
posted @ 2022-09-16 16:44  kallenkal  阅读(65)  评论(0)    收藏  举报