当前位置: 首页 > news >正文

Java详解LeetCode 热题 100(18):LeetCode 73. 矩阵置零(Set Matrix Zeroes)详解

文章目录

    • 1. 题目描述
    • 2. 理解题目
    • 3. 解法一:使用两个额外数组标记法
      • 3.1 思路
      • 3.2 Java代码实现
      • 3.3 代码详解
      • 3.4 复杂度分析
      • 3.5 适用场景
    • 4. 解法二:使用矩阵的第一行和第一列作为标记
      • 4.1 思路
      • 4.2 Java代码实现
      • 4.3 代码详解
      • 4.4 复杂度分析
      • 4.5 适用场景
    • 5. 解法三:使用一个标记变量的优化方法
      • 5.1 思路
      • 5.2 Java代码实现
      • 5.3 代码详解
      • 5.4 复杂度分析
      • 5.5 与解法二的比较
    • 6. 详细步骤分析与示例跟踪
      • 6.1 示例1跟踪:基本情况
      • 6.2 示例2跟踪:边界情况
      • 6.3 示例3跟踪:全零矩阵
      • 6.4 示例4跟踪:单一元素矩阵
    • 7. 常见错误与优化
      • 7.1 常见错误
      • 7.2 性能优化

1. 题目描述

给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。

示例 1:

输入: 
[[1,1,1],[1,0,1],[1,1,1]
]
输出: 
[[1,0,1],[0,0,0],[1,0,1]
]

示例 2:

输入: 
[[0,1,2,0],[3,4,5,2],[1,3,1,5]
]
输出: 
[[0,0,0,0],[0,4,5,0],[0,3,1,0]
]

进阶:

  • 一个直观的解决方案是使用 O(mn) 的额外空间,但这不是一个好的解决方案。
  • 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
  • 你能想出一个仅使用常量空间的解决方案吗?

2. 理解题目

这道题要求我们在给定的矩阵中,如果发现某个元素为0,就将该元素所在的整行和整列都设置为0。具体来说:

  • 输入是一个 m×n 的二维整数矩阵
  • 我们需要找出所有值为0的元素,并将其所在的行和列全部置为0
  • 要求使用原地算法(即不创建新的矩阵)完成操作
  • 进阶要求是优化空间复杂度,理想情况下只使用常量额外空间

关键点:

  1. 不能简单地一边遍历一边置零,因为这样会导致原本不应该置零的元素被错误地置零
  2. 需要记录哪些行和列需要被置零
  3. 如何高效地记录这些信息,是解题的关键

3. 解法一:使用两个额外数组标记法

3.1 思路

最直观的解法是使用两个额外的数组来记录哪些行和列需要被置为0:

  1. 使用一个大小为m的布尔数组row记录哪些行需要置零
  2. 使用一个大小为n的布尔数组col记录哪些列需要置零
  3. 首先遍历整个矩阵,标记包含0的行和列
  4. 然后再次遍历矩阵,根据标记数组将相应的行和列置零

这种方法的空间复杂度为O(m + n),满足进阶要求中的第二点。

3.2 Java代码实现

class Solution {public void setZeroes(int[][] matrix) {// 获取矩阵的行数和列数int m = matrix.length;int n = matrix[0].length;// 创建两个布尔数组,分别记录哪些行和列需要置零boolean[] row = new boolean[m];boolean[] col = new boolean[n];// 第一次遍历:标记需要置零的行和列for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (matrix[i][j] == 0) {row[i] = true;col[j] = true;}}}// 第二次遍历:根据标记将相应的行和列置零for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (row[i] || col[j]) {matrix[i][j] = 0;}}}}
}

3.3 代码详解

详细解释每一步的意义和实现:

// 获取矩阵的行数和列数
int m = matrix.length;
int n = matrix[0].length;
  • 获取输入矩阵的维度,m表示行数,n表示列数
  • 这是处理二维数组时的常见做法
// 创建两个布尔数组,分别记录哪些行和列需要置零
boolean[] row = new boolean[m];
boolean[] col = new boolean[n];
  • 创建两个布尔类型的数组:
    • row数组大小为m,用于标记哪些行需要置零
    • col数组大小为n,用于标记哪些列需要置零
  • 布尔数组的默认值为false,表示初始状态下没有行或列需要置零
// 第一次遍历:标记需要置零的行和列
for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (matrix[i][j] == 0) {row[i] = true;col[j] = true;}}
}
  • 遍历整个矩阵,检查每个元素的值
  • 当发现某个位置(i,j)的元素为0时:
    • row[i]标记为true,表示第i行需要置零
    • col[j]标记为true,表示第j列需要置零
  • 这样,第一次遍历结束后,我们就知道了哪些行和列需要被置零
// 第二次遍历:根据标记将相应的行和列置零
for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (row[i] || col[j]) {matrix[i][j] = 0;}}
}
  • 再次遍历矩阵,根据rowcol数组的标记决定是否将元素置零
  • 如果元素所在的行row[i]或列col[j]被标记为true,则将该元素置为0
  • 这样就完成了原地修改矩阵的操作

3.4 复杂度分析

  • 时间复杂度: O(mn),其中 m 是矩阵的行数,n 是矩阵的列数。需要两次遍历整个矩阵。
  • 空间复杂度: O(m + n),使用了两个额外的数组来存储需要置零的行和列的信息。

3.5 适用场景

这种解法是解决矩阵置零问题的基础方法,适用于大多数情况。特别是当空间复杂度要求不是特别严格,允许使用O(m + n)额外空间时,这种方法简单直观,容易实现和理解。

4. 解法二:使用矩阵的第一行和第一列作为标记

4.1 思路

为了进一步优化空间复杂度,我们可以利用矩阵的第一行和第一列来记录哪些行和列需要置零,从而避免使用额外的数组:

  1. 用两个变量firstRowZerofirstColZero记录第一行和第一列是否原本包含0
  2. 使用矩阵的第一行和第一列作为标记数组,记录其余行列是否需要置零
  3. 根据标记,将相应的行和列置零
  4. 最后,根据firstRowZerofirstColZero的值决定是否将第一行和第一列置零

这种方法的空间复杂度为O(1),满足进阶要求中的第三点。

4.2 Java代码实现

class Solution {public void setZeroes(int[][] matrix) {int m = matrix.length;int n = matrix[0].length;// 记录第一行和第一列是否原本包含0boolean firstRowZero = false;boolean firstColZero = false;// 检查第一行是否有0for (int j = 0; j < n; j++) {if (matrix[0][j] == 0) {firstRowZero = true;break;}}// 检查第一列是否有0for (int i = 0; i < m; i++) {if (matrix[i][0] == 0) {firstColZero = 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++) {for (int j = 1; j < n; j++) {if (matrix[i][0] == 0 || matrix[0][j] == 0) {matrix[i][j] = 0;}}}// 如果第一行原本有0,则将第一行全部置零if (firstRowZero) {for (int j = 0; j < n; j++) {matrix[0][j] = 0;}}// 如果第一列原本有0,则将第一列全部置零if (firstColZero) {for (int i = 0; i < m; i++) {matrix[i][0] = 0;}}}
}

4.3 代码详解

详细解释每一步的意义和实现:

// 记录第一行和第一列是否原本包含0
boolean firstRowZero = false;
boolean firstColZero = false;
  • 使用两个布尔变量记录第一行和第一列是否原本包含0
  • 这是必要的,因为我们将使用第一行和第一列来标记其他行列是否需要置零
// 检查第一行是否有0
for (int j = 0; j < n; j++) {if (matrix[0][j] == 0) {firstRowZero = true;break;}
}// 检查第一列是否有0
for (int i = 0; i < m; i++) {if (matrix[i][0] == 0) {firstColZero = true;break;}
}
  • 单独检查第一行和第一列是否包含0
  • 如果包含,则相应的标记变量设为true
// 使用第一行和第一列作为标记
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; // 标记该列需要置零}}
}
  • 从矩阵的第二行和第二列开始遍历(跳过第一行和第一列)
  • 当发现元素matrix[i][j]为0时:
    • 将第i行的第一个元素matrix[i][0]置为0,表示第i行需要全部置零
    • 将第j列的第一个元素matrix[0][j]置为0,表示第j列需要全部置零
// 根据第一行和第一列的标记,将对应的行和列置零
for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {if (matrix[i][0] == 0 || matrix[0][j] == 0) {matrix[i][j] = 0;}}
}
  • 再次遍历矩阵(跳过第一行和第一列)
  • 如果元素所在行的第一个元素为0,或者所在列的第一个元素为0,则将该元素置为0
// 如果第一行原本有0,则将第一行全部置零
if (firstRowZero) {for (int j = 0; j < n; j++) {matrix[0][j] = 0;}
}// 如果第一列原本有0,则将第一列全部置零
if (firstColZero) {for (int i = 0; i < m; i++) {matrix[i][0] = 0;}
}
  • 最后,根据之前保存的firstRowZerofirstColZero变量的值
  • 决定是否需要将第一行和第一列全部置零

4.4 复杂度分析

  • 时间复杂度: O(mn),其中 m 是矩阵的行数,n 是矩阵的列数。需要进行多次遍历,但总的操作次数与矩阵大小成正比。
  • 空间复杂度: O(1),只使用了常数额外空间。

4.5 适用场景

这种解法特别适合空间要求严格的场景,它巧妙地利用了矩阵本身的存储空间,避免了使用额外的数组。在面试中,如果被要求优化空间复杂度,这种方法是一个很好的解决方案。

5. 解法三:使用一个标记变量的优化方法

5.1 思路

我们可以进一步优化解法二,只使用一个标记变量:

  1. 用一个变量firstColZero记录第一列是否原本包含0
  2. 使用矩阵的第一行来标记列是否需要置零,使用第一列来标记行是否需要置零
  3. 第一行是否需要置零可以用matrix[0][0]来标记
  4. 根据标记,将相应的行和列置零

这种方法同样具有O(1)的空间复杂度,但代码更加简洁。

5.2 Java代码实现

class Solution {public void setZeroes(int[][] matrix) {int m = matrix.length;int n = matrix[0].length;// 标记第一列是否原本包含0boolean firstColZero = false;// 第一次遍历,标记需要置零的行和列for (int i = 0; i < m; i++) {// 检查第一列是否有0if (matrix[i][0] == 0) {firstColZero = true;}// 从第二列开始遍历,标记第一行和第一列for (int j = 1; j < n; j++) {if (matrix[i][j] == 0) {matrix[i][0] = 0; // 标记该行需要置零matrix[0][j] = 0; // 标记该列需要置零}}}// 从最后一行和最后一列开始,根据标记置零for (int i = m - 1; i >= 0; i--) {for (int j = n - 1; j >= 1; j--) {if (matrix[i][0] == 0 || matrix[0][j] == 0) {matrix[i][j] = 0;}}// 处理第一列if (firstColZero) {matrix[i][0] = 0;}}}
}

5.3 代码详解

详细解释每一步的意义和实现:

// 标记第一列是否原本包含0
boolean firstColZero = false;
  • 只使用一个布尔变量记录第一列是否原本包含0
  • 第一行是否包含0将通过matrix[0][0]隐式表示
// 第一次遍历,标记需要置零的行和列
for (int i = 0; i < m; i++) {// 检查第一列是否有0if (matrix[i][0] == 0) {firstColZero = true;}// 从第二列开始遍历,标记第一行和第一列for (int j = 1; j < n; j++) {if (matrix[i][j] == 0) {matrix[i][0] = 0; // 标记该行需要置零matrix[0][j] = 0; // 标记该列需要置零}}
}
  • 遍历整个矩阵
  • 记录第一列是否有0
  • 当发现元素matrix[i][j]为0时(从第二列开始):
    • 将第i行的第一个元素置为0
    • 将第j列的第一个元素置为0
// 从最后一行和最后一列开始,根据标记置零
for (int i = m - 1; i >= 0; i--) {for (int j = n - 1; j >= 1; j--) {if (matrix[i][0] == 0 || matrix[0][j] == 0) {matrix[i][j] = 0;}}// 处理第一列if (firstColZero) {matrix[i][0] = 0;}
}
  • 从矩阵的右下角开始,向左上方向遍历
  • 根据第一行和第一列的标记,将对应的元素置零
  • 最后,根据firstColZero的值决定是否将第一列的元素置零

这种从后向前的遍历顺序是必要的,因为它确保了我们先处理依赖于标记的元素,最后才处理作为标记的第一行和第一列。

5.4 复杂度分析

  • 时间复杂度: O(mn),与解法二相同。
  • 空间复杂度: O(1),只使用了一个额外的布尔变量。

5.5 与解法二的比较

解法三和解法二的核心思想相同,都是利用矩阵的第一行和第一列作为标记。主要区别在于:

  1. 解法三只使用一个布尔变量,而解法二使用两个
  2. 解法三的遍历顺序是从后向前,确保了标记不会被提前修改
  3. 解法三代码稍微复杂一些,但效率略高

在实际应用中,这两种解法的性能差异不大,可以根据个人习惯和理解程度选择使用。

6. 详细步骤分析与示例跟踪

让我们通过几个具体的例子,详细跟踪每种解法的执行过程,以加深理解。

6.1 示例1跟踪:基本情况

输入矩阵:

[[1,1,1],[1,0,1],[1,1,1]
]

使用解法一(两个额外数组)跟踪:

  1. 初始化

    • m = 3, n = 3
    • row = [false, false, false]
    • col = [false, false, false]
  2. 第一次遍历,标记包含0的行和列

    • 发现matrix[1][1] = 0
    • 更新row[1] = true, col[1] = true
    • 此时row = [false, true, false], col = [false, true, false]
  3. 第二次遍历,根据标记置零

    • 根据row和col数组,将相应位置的元素置为0
    • 第1行(row[1]=true)的所有元素置为0
    • 第1列(col[1]=true)的所有元素置为0
  4. 最终矩阵

    [[1,0,1],[0,0,0],[1,0,1]
    ]
    

使用解法二(利用第一行和第一列作为标记)跟踪:

  1. 初始化

    • m = 3, n = 3
    • firstRowZero = false, firstColZero = false
  2. 检查第一行和第一列

    • 第一行没有0,firstRowZero = false
    • 第一列没有0,firstColZero = false
  3. 使用第一行和第一列标记

    • 发现matrix[1][1] = 0
    • 更新matrix[1][0] = 0和matrix[0][1] = 0
  4. 此时矩阵状态

    [[1,0,1],[0,0,1],[1,1,1]
    ]
    
  5. 根据标记置零

    • 对于matrix[1][1],因为matrix[1][0] = 0或matrix[0][1] = 0,所以置为0
    • 对于matrix[1][2],因为matrix[1][0] = 0,所以置为0
    • 对于matrix[2][1],因为matrix[0][1] = 0,所以置为0
  6. 最终矩阵

    [[1,0,1],[0,0,0],[1,0,1]
    ]
    

6.2 示例2跟踪:边界情况

输入矩阵:

[[0,1,2,0],[3,4,5,2],[1,3,1,5]
]

使用解法三(一个标记变量)跟踪:

  1. 初始化

    • m = 3, n = 4
    • firstColZero = false
  2. 第一次遍历

    • 检查第一列,发现matrix[0][0] = 0,设置firstColZero = true
    • 标记过程如下:
      • matrix[0][0] = 0(发现matrix[0][0] = 0,无需标记)
      • matrix[0][3] = 0(发现matrix[0][3] = 0,无需标记)
      • matrix[0][0] = 0, matrix[0][3] = 0(已经是0,无需更改)
  3. 此时矩阵状态

    [[0,1,2,0],[3,4,5,2],[1,3,1,5]
    ]
    
    • firstColZero = true
  4. 从后向前遍历,根据标记置零

    • 根据第一行和第一列的标记,应将第0列和第3列的所有元素置为0
    • 逐步更新后的矩阵:
    [[0,1,2,0],[0,4,5,0],[0,3,1,0]
    ]
    
  5. 最终矩阵

    [[0,0,0,0],[0,4,5,0],[0,3,1,0]
    ]
    

6.3 示例3跟踪:全零矩阵

输入矩阵:

[[0,0],[0,0]
]

使用解法一跟踪:

  1. 初始化

    • m = 2, n = 2
    • row = [false, false]
    • col = [false, false]
  2. 第一次遍历,标记包含0的行和列

    • 所有元素都是0
    • 更新row = [true, true], col = [true, true]
  3. 第二次遍历,根据标记置零

    • 所有行和列都需要置零
    • 矩阵保持不变
  4. 最终矩阵

    [[0,0],[0,0]
    ]
    

6.4 示例4跟踪:单一元素矩阵

输入矩阵:

[[1]
]

使用解法二跟踪:

  1. 初始化

    • m = 1, n = 1
    • firstRowZero = false, firstColZero = false
  2. 检查第一行和第一列

    • 只有一个元素,且不为0
    • firstRowZero = false, firstColZero = false
  3. 使用第一行和第一列标记

    • 没有元素需要标记
  4. 最终矩阵

    [[1]
    ]
    

7. 常见错误与优化

7.1 常见错误

  1. 直接在遍历过程中修改矩阵
    这是最常见的错误。如果在第一次遍历时就直接将元素所在的行和列置零,会导致后续判断时的错误。

    // 错误方法
    for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (matrix[i][j] == 0) {// 直接修改行和列,会影响后续判断for (int k = 0; k < n; k++) matrix[i][k] = 0;for (int k = 0; k < m; k++) matrix[k][j] = 0;}}
    }
    

    这种方法会导致矩阵中的所有元素最终都被置为0,因为一旦将某行或某列置零,后续遍历到这些位置时,又会将更多的行和列置零。

  2. 忘记记录第一行和第一列的状态
    在解法二和解法三中,使用第一行和第一列作为标记。如果忘记先记录它们本身是否包含0,会导致错误的结果。

    // 错误方法
    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;}}
    }
    // 忘记检查第一行和第一列原本是否包含0
    
  3. 标记和置零顺序错误
    在解法三中,如果先处理第一行或第一列,会导致标记信息丢失,影响后续元素的置零操作。

    // 错误的处理顺序
    for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (matrix[i][0] == 0 || matrix[0][j] == 0) {matrix[i][j] = 0;}}
    }
    // 从前向后处理会破坏标记信息
    
  4. 边界情况处理不当
    忘记处理矩阵为空或只有一行/一列的特殊情况。

    // 忘记处理边界情况
    public void setZeroes(int[][] matrix) {// 没有检查矩阵是否为空int m = matrix.length;int n = matrix[0].length; // 如果matrix为空,会抛出异常// ...
    }
    

7.2 性能优化

  1. 提前返回全零矩阵
    如果发现矩阵中的0特别多,可以考虑提前判断是否需要将整个矩阵置零。

    // 优化:检查是否需要将整个矩阵置零
    boolean allZeroes = true;
    for (int i = 0; i < m && allZeroes; i++) {for (int j = 0; j < n; j++) {if (matrix[i][j] != 0) {allZeroes = false;break;}}
    }
    if (allZeroes) return; // 如果矩阵全是0,无需处理
    
  2. 使用位运算优化空间
    对于行数和列数较小的矩阵,可以使用整数的位来记录哪些行和列需要置零,从而进一步降低空间复杂度。

    // 使用位运算记录行列状态(适用于m,n <= 32的情况)
    int rowBits = 0;
    int colBits = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (matrix[i][j] == 0) {rowBits |= (1 << i); // 设置第i位colBits |= (1 << j); // 设置第j位}}
    }for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (((rowBits >> i) & 1) == 1 || ((colBits >> j) & 1) == 1) {matrix[i][j] = 0;}}
    }
    
  3. 合并遍历
    对于某些特殊情况,可以尝试合并多次遍历,减少循环次数。

    // 标记和处理第一行的同时,记录第一列的状态
    boolean firstColZero = false;
    for (int i = 0; i < m; i++) {if (matrix[i][0] == 0) firstColZero = true;for (int j = 1; j < n; j++) {// 处理其余部分}
    }
    
  4. 使用队列记录零元素位置
    另一种思路是使用队列记录所有零元素的位置,然后再次遍历时只处理这些位置的行和列。

    Queue<int[]> zeroPositions = new LinkedList<>();
    // 记录所有0的位置
    for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (matrix[i][j] == 0) {zeroPositions.offer(new int[]{i, j});}}
    }// 处理记录的位置
    while (!zeroPositions.isEmpty()) {int[] pos = zeroPositions.poll();int row = pos[0], col = pos[1];// 将该行和该列置零for (int j = 0; j < n; j++) matrix[row][j] = 0;for (int i = 0; i < m; i++) matrix[i][col] = 0;
    }
    

    这种方法适用于矩阵中0很少的情况,但空间复杂度为O(k),其中k是矩阵中0的数量。

相关文章:

Java详解LeetCode 热题 100(18):LeetCode 73. 矩阵置零(Set Matrix Zeroes)详解

文章目录 1. 题目描述2. 理解题目3. 解法一&#xff1a;使用两个额外数组标记法3.1 思路3.2 Java代码实现3.3 代码详解3.4 复杂度分析3.5 适用场景 4. 解法二&#xff1a;使用矩阵的第一行和第一列作为标记4.1 思路4.2 Java代码实现4.3 代码详解4.4 复杂度分析4.5 适用场景 5. …...

MySQL刷题 Day08

LC 1341电影评分 本题思路简单&#xff0c;但一不注意就错了 &#xff1a; 不难想到用union&#xff0c;写出如下代码&#xff1a; (select u.name results from MovieRating mr left join Users u on mr.user_id u.user_id group by mr.user_id order by count(mr.user_id…...

linux查看本机服务器的外网IP命令

在 Linux 中查看本机服务器的外网 IP&#xff08;公网 IP&#xff09;可以通过以下几种方法&#xff1a; 1. 使用 curl 查询外部服务&#xff08;推荐&#xff09; curl ifconfig.me或&#xff1a; curl icanhazip.com或&#xff1a; curl ipinfo.io/ip这些服务会返回你的公…...

DVWA-XSS

DOM low 这是一个下拉框的形式&#xff0c;但是如果我们不让他等于English呢&#xff0c;换成js代码呢&#xff1f; <script>alert(xss);</script> Medium <script> 标签&#xff0c;但仅使用简单的字符串匹配进行替换&#xff08;比如移除 "<scr…...

第15天-NumPy科学计算实战:从基础到图像处理

一、NumPy核心优势 高效数组运算:矢量操作比纯Python快10-100倍 广播机制:不同形状数组的算术运算 内存优化:连续内存块存储,支持大数据处理 丰富API:线性代数、傅里叶变换、随机数生成等 二、环境准备 pip install numpy matplotlib 三、基础操作演示 1. 创建数组 im…...

Spring Boot + +小程序, 快速开发零工市场小程序

现在零工经济发展的越来越好&#xff0c;不止是很多人想要利用空余时间找零工赚外快&#xff0c;也有很多企业有灵活用工的需求&#xff0c;根据这样的需求&#xff0c;我们利用Spring Boot 和小程序&#xff0c;快速开发出了零工市场小程序。 利用 Spring Boot 开发零工市场小…...

Vue 3.0中核心的Composition API

在当今快速发展的前端生态系统中&#xff0c;Vue 3.0以其革命性的Composition API重新定义了组件开发的范式。作为Vue框架的一次重大进化&#xff0c;Composition API不仅解决了Options API在复杂组件中面临的逻辑复用和组织难题&#xff0c;更为开发者提供了更灵活、更强大的代…...

洛谷B3840 [GESP202306 二级] 找素数

题目描述 小明刚刚学习了素数的概念&#xff1a;如果一个大于 1 的正整数&#xff0c;除了 1 和它自身外&#xff0c;不能被其他正整数整除&#xff0c;则这个正整数是素数。现在&#xff0c;小明想找到两个正整数 A 和 B 之间&#xff08;包括 A 和 B&#xff09;有多少个素数…...

Axure设计之带分页的穿梭框原型

穿梭框&#xff08;Transfer&#xff09;是一种常见且实用的交互组件&#xff0c;广泛应用于需要批量选择或分配数据的场景。 一、应用场景 其典型应用场景包括&#xff1a; 权限管理系统&#xff1a;批量分配用户角色或系统权限数据筛选工具&#xff1a;在大数据集中选择特…...

VsCode开发环境之Node.js离线部署

1.下载node部署文件 地址为&#xff1a;CNPM Binaries Mirror 2.下载后解压 3.验证版本 4.配置环境变量 5.外网寻找一个对应项目的npm文件--node_modules 6.node_modules文件夹复制到node.js的路径下 7.接着就可以正常运行了。...

补充Depends 和 request: Request 依赖注入用法的注意事项

不要在非路由函数&#xff08;如类的 __init__ 方法或普通模块函数&#xff09;中直接使用 Depends() 或 request。 Depends 和 request: Request 是 FastAPI 提供的依赖注入机制的一部分&#xff0c;仅适用于FastAPI 路由函数或由 FastAPI 调用的依赖函数中。在类初始化、模块…...

uniapp-商城-64-后台 商品列表(商品修改---页面跳转,深浅copy应用,递归调用等)

完成了商品的添加和展示&#xff0c;下面的文字将继续进行商品页面的处理&#xff0c;主要为商品信息的修改的页面以及后天逻辑的处理。 本文主要介绍了商品信息修改页面的实现过程。首先&#xff0c;页面布局包括编辑和删除功能&#xff0c;未来还可添加上架和下架按钮。通过c…...

【MySQL】联合查询(上)

目录 一. 什么是联合查询 二. 笛卡尔积 三. 内连接查询 示例演示 四. 外连接 示例演示 五. 自连接 自连接 示例演示 一. 什么是联合查询 在之前学习的增删改查中都是对于单表进行查询&#xff0c;但是因为在数据库设计时需要遵循范式的要求&#xff0c;数据就会被拆分到多…...

Model 是 Agent 的大脑(以camel为例)

Model 是 Agent 的大脑&#xff0c;负责处理所有输入和输出数据。通过有效调用不同的模型&#xff0c;智能体可以根据任务需求执行文本分析、图像识别和复杂推理等操作。CAMEL 提供了一系列标准和可定制的接口&#xff0c;并与各种组件无缝集成&#xff0c;以赋能大语言模型&am…...

Linux条件变量

在 Linux 系统中&#xff0c;pthread_cond_init() 函数和条件变量&#xff08;Condition Variable&#xff09;是多线程编程中用于线程同步的核心机制。它们通过协调线程间的等待与通知逻辑&#xff0c;解决共享资源的竞争问题。以下从功能、工作机制、使用场景和注意事项等方面…...

k8s-NetworkPolicy

在 Kubernetes 中&#xff0c;NetworkPolicy 是一种资源对象&#xff0c;用于定义 Pod 之间的网络通信策略。它允许你控制哪些 Pod 可以相互通信&#xff0c;以及如何通信。通过使用 NetworkPolicy&#xff0c;可以实现更细粒度的网络访问控制&#xff0c;增强集群的安全性。 1…...

什么是“架构孤岛”?如何识别与整合?为什么现代企业在追求敏捷开发的同时,反而更容易陷入架构孤岛陷阱?

在现代信息技术飞速发展的时代,系统架构日益复杂,组织在构建与演进其信息系统时,面临着前所未有的挑战。然而,就在不断追求敏捷性、可扩展性与数字化创新的过程中,一个被广泛忽视却日益严峻的问题悄然浮现——“架构孤岛”。它们像岛屿一样,彼此孤立,通信不畅,数据难以…...

nfs存储IO等待,导致k8s业务系统卡慢问题处理

注:服务器配置:64C,128G,麒麟v10系统,系统磁盘使用空间(5T)均低于50%,存储磁盘iops约为800左右 发现业务系统卡慢,使用top 命令查看.系统负载较高长期保持在60以上,发现wa值的指标参数长期高于15,返现CPU用于写入磁盘IO等待的时间较高,系统的磁盘I/O压力较大. 配合开发查看日志…...

如何使用两块硬盘作为 Ubuntu24 的系统盘,实现坏掉一块不影响系统运行。

最近我想使用Ubuntu组一个NAS系统&#xff0c;想实现系统盘冗余&#xff0c;各位大佬可以给点建议吗。 Deep Seek 为了实现两块硬盘作为 Ubuntu 24 系统盘的冗余配置&#xff08;RAID 1&#xff09;&#xff0c;确保一块硬盘损坏时系统仍可运行&#xff0c;以下是详细步骤&am…...

电子电气架构 --- 细化造车阶段流程

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…...

物联网之使用Vertx实现UDP最佳实践【响应式】

小伙伴们&#xff0c;你们好呀&#xff0c;我是老寇&#xff0c;跟我一起学习使用Vertx实现UDP-Server 实现UDP【响应式】 Vertx-Core地址 注意 UDP是无连接的传输&#xff0c;这意味着您与远程客户端没有建立持续的连接。 所以&#xff0c;您发送和接收的数据包都要包含有…...

代码管理平台Gitlab如何通过快解析实现远程访问?

一、Gitlab功能介绍 Gitlab是被广泛使用的基于git的开源代码管理平台&#xff0c;用于管理、存储开发人员代码&#xff0c;同时可以协同开发 二、外网试用Gitlab遇到的问题 运维人员将Gitlab服务器部署在总部机房&#xff0c;而分公司开发人员和出差运维人员就无法访问Gitlab…...

七彩喜防摔马甲:科技守护银发安全的“隐形铠甲”

随着现代人生活方式的多样化&#xff0c;尤其是在户外运动和骑行等活动中&#xff0c;安全问题日益受到重视。 七彩喜防摔马甲&#xff0c;作为一款兼具防护性与舒适性的智能穿戴设备&#xff0c;正在改变人们对传统防护装备的认知。 创新设计 防摔马甲的设计灵感来源于人体…...

IDEA推送到gitlab,jenkins识别,然后自动发布到需要的主机

实验环境 192.168.8.100 gitlab 192.168.8.200 jenkins mvn 192.168.8.10 测试主机 默认都关闭了防火墙和setenforce 实验要求 实验在IDEA上面推送代码然后gitlab推送给jenkins&#xff0c;然后mvn构建&#xff0c;最后发布到测试主机上面 实验开始 在tomcat上安装manve…...

五、【API 开发篇(下)】:使用 Django REST Framework构建测试用例模型的 CRUD API

【API 开发篇】&#xff1a;使用 Django REST Framework构建测试用例模型的 CRUD API 前言第一步&#xff1a;增强 Serializers (序列化器) - 处理关联和选择项第二步&#xff1a;创建 TestCaseViewSet (视图集) - 支持过滤第三步&#xff1a;注册 TestCaseViewSet 到 Router第…...

IDEA推送到gitlab,jenkins识别,然后自动发布到需要的主机(流水线)

jenkins流水线 新建项目 找到流水线选择脚本 3.点击流水线语法开始编辑脚本 4.生成流水线脚本复制 5.修改脚本 6.继续添加(手打) 7.继续生成添加 8.最终脚本 9.保存测试 10.构建 11.访问主页查看是否修改...

四、【API 开发篇 (上)】:使用 Django REST Framework 构建项目与模块 CRUD API

【API 开发篇 】&#xff1a;使用 Django REST Framework 构建项目与模块 CRUD API 前言为什么选择 Django REST Framework (DRF)&#xff1f;第一步&#xff1a;创建 Serializers (序列化器)第二步&#xff1a;创建 ViewSets (视图集)第三步&#xff1a;配置 URLs (路由)第四步…...

vscode连接本地Ubuntu

因为在学习项目的时候&#xff0c;自己的云服务器性能太差一直要编译很长时间&#xff0c;而且总是连接失败&#xff0c;所以搞了一个Ubuntu25.04的系统在自己的vmare中。 其中参考了以下文章。 Ubuntu 24.04 桌面版安装指南(2025版) | 官网镜像下载启动盘制作保姆级图文教程…...

idea无法识别Maven项目

把.mvn相关都删除了 导致Idea无法识别maven项目 或者 添加导入各个模块 最后把父模块也要导入...

Redis应用--缓存

目录 一、什么是缓存 1.1 二八定律 二、使用Redis作为缓存 三、缓存的更新策略 3.1 定期更新 3.2 实时生成 四、缓存预热、缓存穿透、缓存雪崩和缓存击穿 4.1 缓存预热 4.2 缓存穿透 4.3 缓存雪崩 4.4 缓存击穿 一、什么是缓存 缓存(cache)是计算机的一个经典的概念…...

大语言模型与人工智能:技术演进、生态重构与未来挑战

目录 技术演进:从专用AI到通用智能的跃迁核心能力:LLM如何重构AI技术栈应用场景:垂直领域的技术革命生态关系:LLM与AI技术矩阵的协同演进挑战局限:智能天花板与伦理困境未来趋势:从语言理解到世界模型1. 技术演进:从专用AI到通用智能的跃迁 1.1 三次技术浪潮的跨越 #me…...

多模态大语言模型arxiv论文略读(八十六)

EVALALIGN: Supervised Fine-Tuning Multimodal LLMs with Human-Aligned Data for Evaluating Text-to-Image Models ➡️ 论文标题&#xff1a;EVALALIGN: Supervised Fine-Tuning Multimodal LLMs with Human-Aligned Data for Evaluating Text-to-Image Models ➡️ 论文作…...

C++--string类对象

一,引言 string类对象在于更好的处理字符串问题&#xff0c;为对于字符串这一类型提供更加方便的接口和运算符的重载。本片文章首先会引入auto关键字和范围for两个C11小语法。之后按照如下网站所提供的顺序经行讲解。cplusplus.com - The C Resources Networkhttps://legacy.c…...

云计算与大数据进阶 | 28、存储系统如何突破容量天花板?可扩展架构的核心技术与实践—— 分布式、弹性扩展、高可用的底层逻辑(下)

在上篇中&#xff0c;我们围绕存储系统可扩展架构详细探讨了基础技术原理与典型实践。然而&#xff0c;在实际应用场景中&#xff0c;存储系统面临的挑战远不止于此。随着数据规模呈指数级增长&#xff0c;业务需求日益复杂多变&#xff0c;存储系统还需不断优化升级&#xff0…...

Python _day31

DAY 31 文件的规范拆分和写法 今日的示例代码包含2个部分 notebook文件夹内的ipynb文件&#xff0c;介绍下今天的思路项目文件夹中其他部分&#xff1a;拆分后的信贷项目&#xff0c;学习下如何拆分的&#xff0c;未来你看到的很多大项目都是类似的拆分方法 知识点回顾 规范的文…...

【JavaWeb】MyBatis

1 介绍 什么是MyBatis? MyBatis是一款优秀的 持久层 框架&#xff0c;用于简化JDBC的开发。 MyBatis本是 Apache的一个开源项目iBatis&#xff0c;2010年这个项目由apache迁移到了google code&#xff0c;并且改名为MyBatis 。2013年11月迁移到Github。 MyBatis官网https://my…...

vue2实现【瀑布流布局】

瀑布流 1. 解释2. 形成结构和样式3. 自定义指令 1. 解释 瀑布流特征&#xff1a; 等宽不等高&#xff1a;元素宽度固定&#xff0c;高度根据内容自适应。错落排列&#xff1a;元素像瀑布一样从上到下依次填充&#xff0c;自动寻找最短列插入 体现&#xff1a;图中第一排1&…...

系统架构设计(十六):敏感点、权衡点、风险点和非风险点

术语定义 概念定义说明敏感点&#xff08;Sensitivity Point&#xff09;架构设计中对某个质量属性有显著影响的点&#xff0c;一旦改变该点&#xff0c;会显著影响系统的某个质量属性。风险点&#xff08;Risk Point&#xff09;由于架构决策带来的潜在失败风险&#xff0c;可…...

优化dp贪心数论

这次三个题目都来自牛客周赛93&#xff0c;个人觉得出的很好&#xff0c;收获颇多。 1.简单贪心 题目意思&#xff1a; 任意选定两个数字&#xff0c;相加之和替代两个数字中的一个&#xff0c;另一个抹除。求操作之后最大字典序之和 思路&#xff1a; 最大字典序之和&…...

详解MySQL 的 binlog,redo log,undo log

MySQL 的 binlog、redo log 和 undo log 是数据库事务处理与数据一致性的核心组件&#xff0c;各自承担不同的职责。 1. binlog&#xff08;二进制日志&#xff09; 定位&#xff1a;MySQL Server 层实现的逻辑日志&#xff0c;与存储引擎无关。作用&#xff1a; 主从复制&…...

SymPy|主元、重新表示、分数、约分表达式、极限、级数、ode、获取值、输出形式

SymPy 是一个 Python 的符号计算库&#xff0c;广泛应用于数学计算、物理建模、工程分析等领域。本文将详细介绍 SymPy 在处理主元操作、重新表示、分数、约分表达式、极限、级数、常微分方程&#xff08;ODE&#xff09;以及获取值和输出形式等方面的应用&#xff0c;通过完整…...

Java 05正则表达式

正则表达式 1.简介 一个字符串&#xff0c;指定一些规则&#xff0c;来校验其他的字符串 String s"";规则 需要进行匹配的字符串.matches(s);来判断2.字符类**&#xff08;单个&#xff09; [abc] String s"[ABC]"; "A".matches(s);返回true…...

IEEE 802.1Q协议下封装的VLAN数据帧格式

1.概要 802.1d定义了生成树 802.1w定义了快速生成树 802.1s定义了多生成树 802.1q定义了VLAN 2.说明 IEEE802.1q协议的作用是&#xff08;生成VLAN标记&#xff09;VLAN编号取值范围&#xff1a;0-4095&#xff0c;其中0和4095是保留编号&#xff0c;所最大值是&#xff…...

VMware三种网络配置对比

​桥接模式&#xff08;Bridged Mode&#xff09;​​ ​​核心特点​​&#xff1a; 虚拟机被视为局域网中的独立设备&#xff0c;直接使用物理网络适配器&#xff0c;需配置与宿主机同一网段的IP地址。 ​​典型场景​​&#xff1a; 虚拟机需对外提供服务&#xff08;如Web…...

再来1章linux系列-19 防火墙 iptables 双网卡主机的内核 firewall-cmd firewalld的高级规则

学习目标&#xff1a; 实验实验需求实验配置内容和分析 &#xff08;每一个设备的每一步操作&#xff09;实验结果验证其他 学习内容&#xff1a; 实验实验需求实验配置内容和分析 &#xff08;每一个设备的每一步操作&#xff09;实验结果验证其他 1.实验 2.实验需求 图…...

Word 转 HTML API 接口

Word 转 HTML API 接口 图像/转换 Word 文档转换为 HTML 文件转换 / 超高精度与还原度 文件转换 / Word。 1. 产品功能 超高精度与还原度的 HTML 文件转换&#xff1b;支持将 Word 文档转换为 HTML 格式&#xff1b;支持 .doc 和 .docx 格式&#xff1b;保持原始 Word 文档的…...

深入解析MATLAB codegen生成MEX文件的原理与优势

一、MATLAB codegen底层工作机制 1.1 MATLAB执行引擎的局限性 MATLAB作为解释型语言&#xff0c;其执行过程包含多个关键步骤&#xff1a; 语法解析&#xff1a;将.m文件代码转换为抽象语法树(AST) 类型推断&#xff1a;运行时动态确定变量类型 内存管理&#xff1a;自动处…...

PEFT简介及微调大模型DeepSeek-R1-Distill-Qwen-1.5B

&#x1f917; PEFT&#xff08;参数高效微调&#xff09;是由Huggingface团队开发的开源框架&#xff0c;专为大型预训练模型&#xff08;如GPT、LLaMA、T5等&#xff09;设计&#xff0c;用于高效地将大型预训练模型适配到各种下游应用&#xff0c;而无需对模型的所有参数进行…...

Python训练营打卡 Day31

文件的规范拆分和写法 今日的示例代码包含2个部分 notebook文件夹内的ipynb文件&#xff0c;介绍下今天的思路项目文件夹中其他部分&#xff1a;拆分后的信贷项目&#xff0c;学习下如何拆分的&#xff0c;未来你看到的很多大项目都是类似的拆分方法 知识点回顾&#xff1a;文件…...

Google精准狙击OpenAI Codex,发布AI编程助手Jules!

自从OpenAI推出 Codex之后&#xff0c;Google就憋不住了&#xff0c;悄悄得瞄准了OpenAI的最新成果。 原计划是是打算在明天举行的Google I/O年度开发者大会上发布相关产品&#xff0c;但Google似乎已经一刻也等不了了。 就在昨天&#xff0c;谷歌正式推出了其AI编程——Ju…...