【没事儿看两道Leetcode系列】100热题之矩阵

矩阵

73. 矩阵置零

image-20250124174031326

原地置零的方法是:

  1. 首先记录首行首列是否存在0。
  2. 对于非首行非首列的每个元素,如果其值=0,则令该行行首和该列列首元素=0,用于标识“这一行/列应当被归零”。
  3. 遍历非首行非首列的所有元素,如果发现该元素所在的行首或列首元素=0,说明这个元素所在的行和列应当被全部归零,则令该元素=0.
  4. 最后再根据之前记录的首行或首列是否存在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. 螺旋矩阵

image-20250124174457898

我自己想的方法:矩阵元素全都>=-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. 旋转图像

image-20250124175007827

这道题我还记得上次的做法:先对角翻转,再水平翻转。

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

image-20250124175203047

答案中比较优秀的一种做法是 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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灰海宽松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值