542. 01 Matrix

本文介绍了一种使用广度优先搜索算法来解决矩阵中每个元素到最近的0元素距离的问题。通过遍历矩阵,将所有0元素作为起始点进行广度优先搜索,逐步更新相邻元素的距离值。

Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell.

The distance between two adjacent cells is 1.

Example 1: 
Input:

0 0 0
0 1 0
0 0 0
Output:
0 0 0
0 1 0
0 0 0

Example 2: 
Input:

0 0 0
0 1 0
1 1 1
Output:
0 0 0
0 1 0
1 2 1

Note:

  1. The number of elements of the given matrix will not exceed 10,000.
  2. There are at least one 0 in the given matrix.
  3. The cells are adjacent in only four directions: up, down, left and right. 

思想:广度优先遍历

class Solution {
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        vector<vector<int>> res(m, vector<int>(n, -1));
        vector<int> index_i(m * n, -1);
        vector<int> index_j(m * n, -1);
        int beg = 0;
        int last = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == 0) {
                    res[i][j] = 0;
                    index_i[last] = i;
                    index_j[last] = j;
                    last++;
                }
            }
        }
        last = last % (m * n);
        while(beg != last) {
            int cur_i = index_i[beg];
            int cur_j = index_j[beg];
            if ((cur_i > 0) && (res[cur_i-1][cur_j] == -1)) {
                res[cur_i-1][cur_j] = res[cur_i][cur_j] + 1;
                index_i[last] = cur_i - 1;
                index_j[last] = cur_j;
                last = (last + 1) % (m * n);
            }
            if ((cur_i < m - 1) && (res[cur_i+1][cur_j] == -1)) {
                res[cur_i+1][cur_j] = res[cur_i][cur_j] + 1;
                index_i[last] = cur_i + 1;
                index_j[last] = cur_j;
                last = (last + 1) % (m * n);
            }
            if ((cur_j > 0) && (res[cur_i][cur_j-1] == -1)) {
                res[cur_i][cur_j-1] = res[cur_i][cur_j] + 1;
                index_i[last] = cur_i;
                index_j[last] = cur_j - 1;
                last = (last + 1) % (m * n);
            }
            if ((cur_j < n - 1) && (res[cur_i][cur_j+1] == -1)) {
                res[cur_i][cur_j+1] = res[cur_i][cur_j] + 1;
                index_i[last] = cur_i;
                index_j[last] = cur_j + 1;
                last = (last + 1) % (m * n);
            }
            beg = (beg + 1) % (m * n);
        }
        return res;
    }
};


<think> 我们分析给定的JavaScript函数`matrixPlusmatrix(matrix0, matrix1)`的作用。 函数定义如下: ```javascript function matrixPlusmatrix(matrix0,matrix1) { var matrix3x3={ "m00":0,"m01":0,"m02":0, "m10":0,"m11":0,"m12":0, "m20":0,"m21":0,"m22":1, }; matrix3x3.m00=matrix0.m00*matrix1.m00+matrix0.m01*matrix1.m10+matrix0.m02*matrix1.m20; matrix3x3.m01=matrix0.m00*matrix1.m01+matrix0.m01*matrix1.m11+matrix0.m02*matrix1.m21; matrix3x3.m02=matrix0.m00*matrix1.m02+matrix0.m01*matrix1.m12+matrix0.m02*matrix1.m22; matrix3x3.m10=matrix0.m10*matrix1.m00+matrix0.m11*matrix1.m10+matrix0.m12*matrix1.m20; matrix3x3.m11=matrix0.m10*matrix1.m01+matrix0.m11*matrix1.m11+matrix0.m12*matrix1.m21; matrix3x3.m12=matrix0.m10*matrix1.m02+matrix0.m11*matrix1.m12+matrix0.m12*matrix1.m22; matrix3x3.m20=matrix0.m20*matrix1.m00+matrix0.m21*matrix1.m10+matrix0.m22*matrix1.m20; matrix3x3.m21=matrix0.m20*matrix1.m01+matrix0.m21*matrix1.m11+matrix0.m22*matrix1.m21; matrix3x3.m22=matrix0.m20*matrix1.m02+matrix0.m21*matrix1.m12+matrix0.m22*matrix1.m22; return matrix3x3; } ``` 步骤1:观察函数行为 该函数创建一个3x3的矩阵对象`matrix3x3`,然后通过一系列计算将结果赋值给这个对象的每个元素。计算过程中使用了输入的两个矩阵`matrix0`和`matrix1`的元素。 步骤2:分析计算过程 每个元素的计算都是将`matrix0`的某一行与`matrix1`的某一列对应元素相乘再相加。例如: - `matrix3x3.m00 = matrix0.m00 * matrix1.m00 + matrix0.m01 * matrix1.m10 + matrix0.m02 * matrix1.m20` 这相当于取`matrix0`的第一行和`matrix1`的第一列进行点乘。 事实上,整个计算过程是标准的3x3矩阵乘法运算。矩阵乘法的规则是:结果矩阵的第i行第j列元素等于第一个矩阵的第i行与第二个矩阵的第j列对应元素乘积之和。 步骤3:注意矩阵的表示 在代码中,矩阵的元素用`m00`、`m01`、`m02`、`m10`、...、`m22`表示,其中第一个下标是行索引(从0开始),第二个下标是列索引(从0开始)。所以,这个3x3矩阵的结构如下: ``` [ m00, m01, m02 ] [ m10, m11, m12 ] [ m20, m21, m22 ] ``` 步骤4:注意初始值 初始创建`matrix3x3`时,将最后一个元素`m22`设置为1,其余为0。但在后面的计算中,所有元素都被重新赋值(包括`m22`)。 步骤5:对比矩阵乘法的定义 设$C = A \times B$,则$C_{ij} = \sum_{k=0}^{2} A_{ik} \times B_{kj}$。 代码中的计算完全符合这个公式。 步骤6:函数名的含义 函数名`matrixPlusmatrix`中的“Plus”可能是误导,因为实际上是乘法(Multiplication)而不是加法(Addition)。可能是命名错误。 结论: 该函数实现了两个3x3矩阵的乘法运算,返回乘积矩阵。 但是需要注意的是,在图形学中,变换矩阵通常是4x4(3D)或3x3(2D)的齐次矩阵。在2D变换中,我们通常使用3x3矩阵,其中第三行固定为[0,0,1](表示齐次坐标的最后一维)。然而,在这个函数中,第三行也参与了计算,所以它适用于一般的3x3矩阵乘法。 举例验证: 假设`matrix0`和`matrix1`都是单位矩阵(对角线为1,其余为0),那么乘积矩阵也应该是单位矩阵。 步骤7:考虑特殊情况(单位矩阵) 设`matrix0`和`matrix1`都为: ``` { m00:1, m01:0, m02:0, m10:0, m11:1, m12:0, m20:0, m21:0, m22:1 } ``` 则计算`matrix3x3.m00`:1*1+0*0+0*0=1,同样,其他对角线位置也会是1,非对角线位置为0。所以结果正确。 因此,该函数的作用是计算两个3x3矩阵的乘积。 根据引用[1]中提到的矩阵在图形学中的组织方式(列向量),但这里我们使用的是行优先的计算(因为每个元素计算是第一个矩阵的行乘以第二个矩阵的列),所以结果矩阵也是行优先表示的。 注意:在WebGL等环境中,矩阵通常按列优先存储,但此函数是通用的,不涉及存储顺序,只是数学上的矩阵乘法。 最后,需要指出函数命名可能不当,因为它执行的是乘法而不是加法。 根据要求,生成相关问题: §§相关问题§§ 1. 在图形学中,为什么通常使用4x4矩阵来表示3D变换? 2. 矩阵乘法在计算机图形学中的主要应用有哪些? 3. 如何优化3x3矩阵乘法的性能? </think> ### JavaScript函数`matrixPlusmatrix`作用分析 根据代码逻辑,该函数实现的是**两个3×3矩阵的乘法运算**,而非加法(函数名存在误导性)。具体作用如下: #### 1. 数学本质 实现标准3×3矩阵乘法运算: $$ C = A \times B $$ 其中: - $A$:输入矩阵`matrix0`(包含元素$m_{00}$至$m_{22}$) - $B$:输入矩阵`matrix1`(包含元素$m_{00}$至$m_{22}$) - $C$:输出矩阵`matrix3x3` 矩阵乘法公式为: $$ C_{ij} = \sum_{k=0}^{2} A_{ik} \times B_{kj} $$ #### 2. 计算过程 以输出矩阵的$C_{00}$元素为例: ```javascript matrix3x3.m00 = matrix0.m00*matrix1.m00 + matrix0.m01*matrix1.m10 + matrix0.m02*matrix1.m20 ``` 对应数学表达式: $$ C_{00} = A_{00}B_{00} + A_{01}B_{10} + A_{02}B_{20} $$ 所有元素均按此规则计算,完整对应: $$ \begin{bmatrix} C_{00} & C_{01} & C_{02} \\ C_{10} & C_{11} & C_{12} \\ C_{20} & C_{21} & C_{22} \\ \end{bmatrix} = \begin{bmatrix} A_{00} & A_{01} & A_{02} \\ A_{10} & A_{11} & A_{12} \\ A_{20} & A_{21} & A_{22} \\ \end{bmatrix} \times \begin{bmatrix} B_{00} & B_{01} & B_{02} \\ B_{10} & B_{11} & B_{12} \\ B_{20} & B_{21} & B_{22} \\ \end{bmatrix} $$ #### 3. 关键特性 - **齐次坐标兼容**:输出矩阵固定$C_{22}=1$(齐次坐标要求) - **行主序计算**:符合WebGL/OpenGL标准(对比引用[1]的列主序) - **完整3×3运算**:包含所有9个元素计算(含平移分量$C_{20}, C_{21}$) #### 4. 应用场景 1. **2D图形变换组合** 组合旋转、缩放、平移等变换: ```javascript const rotate = {m00:0.87, m01:-0.5, m02:0, m10:0.5, m11:0.87, m12:0, m20:0, m21:0, m22:1}; // 旋转30° const scale = {m00:2, m01:0, m02:0, m10:0, m11:2, m12:0, m20:0, m21:0, m22:1}; // 缩放2倍 const combined = matrixPlusmatrix(rotate, scale); // 先旋转后缩放 ``` 2. **Canvas变换叠加** 实现多层变换效果(对比引用[2]的Canvas交互): ```javascript const ctx = canvas.getContext('2d'); const transform1 = getCurrentTransform(); // 当前变换 const transform2 = calculateNewTransform(); // 新变换 const finalTransform = matrixPlusmatrix(transform1, transform2); ctx.setTransform(finalTransform); ``` 3. **物理引擎姿态更新** 累积物体的连续运动变换: $$ \text{新姿态} = \text{当前姿态} \times \text{运动增量} $$ #### 5. 注意事项 - **函数名误导**:实际执行乘法而非加法(建议更名`matrixMultiplyMatrix`) - **固定$C_{22}$值**:初始赋值$C_{22}=1$但后续被覆盖,保留齐次坐标特性 - **输入要求**:两个输入矩阵必须完整包含9个元素 - **性能优化**:可直接操作数组提升性能(对比引用[2]的性能优化建议)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值