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

Java详解LeetCode 热题 100(14):LeetCode 56. 合并区间(Merge Intervals)详解

文章目录

    • 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. 解法三:TreeMap法
      • 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 性能优化
    • 8. 扩展题目与应用
      • 8.1 区间插入
      • 8.2 区间列表的交集
      • 8.3 会议室问题
    • 9. 实际应用场景
    • 10. 完整的 Java 解决方案
    • 11. 总结与技巧
      • 11.1 解题要点
      • 11.2 学习收获
      • 11.3 面试技巧
    • 12. 参考资料

1. 题目描述

给出一个区间的集合,请合并所有重叠的区间。

示例 1:

输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入: intervals = [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间,因为它们共享端点4。

提示:

  • 1 <= intervals.length <= 10^4
  • intervals[i].length == 2
  • 0 <= intervals[i][0] <= intervals[i][1] <= 10^4

进阶: 你能设计一个时间复杂度为 O(nlogn) 的算法解决此问题吗?

2. 理解题目

这道题要求我们合并所有重叠的区间。具体来说:

  • 输入是一个二维数组,每个子数组表示一个区间 [start, end]
  • 如果两个区间有重叠,我们需要将它们合并成一个更大的区间
  • 重叠的定义:两个区间 [a, b] 和 [c, d] 重叠,当且仅当 a ≤ d 且 c ≤ b
  • 合并后的区间是 [min(a, c), max(b, d)]

关键点:

  1. 区间可能以任意顺序给出
  2. 区间可能完全包含另一个区间
  3. 边界相等也被视为重叠(如示例2)

3. 解法一:排序 + 一次遍历法

3.1 思路

最高效的解法是先排序再合并:

  1. 按照区间的起始位置对所有区间进行排序
  2. 遍历排序后的区间列表,将重叠的区间合并

排序确保了相邻的重叠区间会排列在一起,这样我们只需要一次遍历就能合并所有重叠的区间。

3.2 Java代码实现

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;class Solution {public int[][] merge(int[][] intervals) {// 处理边界情况if (intervals == null || intervals.length <= 1) {return intervals;}// 按照区间的起始位置排序Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));// 用于存储合并后的区间List<int[]> result = new ArrayList<>();// 将第一个区间加入结果int[] currentInterval = intervals[0];result.add(currentInterval);// 遍历剩余区间for (int i = 1; i < intervals.length; i++) {// 获取当前遍历到的区间int[] interval = intervals[i];// 如果当前区间的起始位置小于等于上一个区间的结束位置,说明有重叠if (interval[0] <= currentInterval[1]) {// 更新当前区间的结束位置为两个区间结束位置的最大值currentInterval[1] = Math.max(currentInterval[1], interval[1]);} else {// 没有重叠,将当前区间加入结果currentInterval = interval;result.add(currentInterval);}}// 将List转换为数组return result.toArray(new int[result.size()][]);}
}

3.3 代码详解

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

// 处理边界情况
if (intervals == null || intervals.length <= 1) {return intervals;
}
  • 如果数组为空或者只有一个区间,不需要合并,直接返回原数组
// 按照区间的起始位置排序
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
  • 使用 Java 8 Lambda 表达式创建一个比较器,按区间的起始位置排序
  • 排序确保了相邻的可能重叠区间会排列在一起
// 用于存储合并后的区间
List<int[]> result = new ArrayList<>();// 将第一个区间加入结果
int[] currentInterval = intervals[0];
result.add(currentInterval);
  • 创建一个动态数组存储合并结果
  • 先将排序后的第一个区间加入结果,作为当前正在处理的区间
// 遍历剩余区间
for (int i = 1; i < intervals.length; i++) {// 获取当前遍历到的区间int[] interval = intervals[i];// 如果当前区间的起始位置小于等于上一个区间的结束位置,说明有重叠if (interval[0] <= currentInterval[1]) {// 更新当前区间的结束位置为两个区间结束位置的最大值currentInterval[1] = Math.max(currentInterval[1], interval[1]);} else {// 没有重叠,将当前区间加入结果currentInterval = interval;result.add(currentInterval);}
}
  • 遍历排序后的区间数组(从第二个开始)
  • 检查当前区间与结果中最后一个区间是否重叠
  • 如果重叠,合并它们(更新结束位置为两者的最大值)
  • 如果不重叠,将当前区间添加到结果中
// 将List转换为数组
return result.toArray(new int[result.size()][]);
  • 将ArrayList转换为要求返回的二维数组

3.4 复杂度分析

  • 时间复杂度: O(n log n),其中 n 是区间的数量。排序需要 O(n log n) 时间,而后续的一次遍历需要 O(n) 时间,总体复杂度由排序决定。
  • 空间复杂度: O(n),需要存储合并后的区间数组。在最坏情况下,没有区间可以合并,我们需要存储所有 n 个区间。排序可能需要 O(log n) 的额外空间。

3.5 适用场景

这种解法是解决区间合并问题的主流方法,适用于绝大多数情况。它简洁高效,容易理解和实现。

4. 解法二:双指针法

4.1 思路

双指针法本质上与解法一相同,但使用两个变量明确跟踪当前合并区间的左右边界,使代码更加清晰:

  1. 对区间按起始位置排序
  2. 设置两个指针 leftright 跟踪当前合并区间的边界
  3. 遍历排序后的区间,根据重叠情况更新指针或添加新区间

4.2 Java代码实现

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;class Solution {public int[][] merge(int[][] intervals) {if (intervals == null || intervals.length <= 1) {return intervals;}// 按照区间的起始位置排序Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));List<int[]> result = new ArrayList<>();// 初始化左右指针int left = intervals[0][0];int right = intervals[0][1];for (int i = 1; i < intervals.length; i++) {// 如果当前区间的起始位置小于等于右指针,说明有重叠if (intervals[i][0] <= right) {// 更新右指针为两个区间结束位置的最大值right = Math.max(right, intervals[i][1]);} else {// 没有重叠,将当前合并后的区间加入结果result.add(new int[]{left, right});// 更新左右指针为当前区间left = intervals[i][0];right = intervals[i][1];}}// 添加最后一个合并后的区间result.add(new int[]{left, right});return result.toArray(new int[result.size()][]);}
}

4.3 代码详解

双指针法的核心在于显式地使用两个变量追踪当前合并区间的边界:

// 初始化左右指针
int left = intervals[0][0];
int right = intervals[0][1];
  • left 跟踪当前合并区间的起始位置
  • right 跟踪当前合并区间的结束位置
  • 初始值设为第一个区间的边界
for (int i = 1; i < intervals.length; i++) {// 如果当前区间的起始位置小于等于右指针,说明有重叠if (intervals[i][0] <= right) {// 更新右指针为两个区间结束位置的最大值right = Math.max(right, intervals[i][1]);} else {// 没有重叠,将当前合并后的区间加入结果result.add(new int[]{left, right});// 更新左右指针为当前区间left = intervals[i][0];right = intervals[i][1];}
}
  • 遍历时检查当前区间是否与已合并区间重叠
  • 如果重叠,只需更新右边界
  • 如果不重叠,将已合并区间加入结果,并重置左右指针为新区间
// 添加最后一个合并后的区间
result.add(new int[]{left, right});
  • 循环结束后,需要将最后一个合并区间添加到结果中

4.4 复杂度分析

  • 时间复杂度: O(n log n),与解法一相同,主要消耗在排序步骤。
  • 空间复杂度: O(n),需要存储合并后的区间数组。

4.5 与解法一的比较

两种解法的核心思想相同,都是先排序再合并,时间和空间复杂度也相同。但双指针法的代码逻辑可能更清晰,特别是在教学或讲解算法时。

5. 解法三:TreeMap法

5.1 思路

TreeMap 是一种有序映射数据结构,可以用来高效地处理区间合并问题,特别是当区间操作比较复杂时。基本思路是:

  1. 使用 TreeMap 存储区间,键为区间起始位置,值为区间结束位置
  2. 遍历原始区间,对于每个区间,查找可能与之重叠的已存在区间
  3. 合并重叠区间,更新 TreeMap

这种方法在处理动态添加区间的场景中特别有用。

5.2 Java代码实现

import java.util.*;class Solution {public int[][] merge(int[][] intervals) {if (intervals == null || intervals.length <= 1) {return intervals;}// 使用 TreeMap 来存储区间,键为起始位置,值为结束位置TreeMap<Integer, Integer> map = new TreeMap<>();// 遍历所有区间for (int[] interval : intervals) {int start = interval[0];int end = interval[1];// 查找小于等于当前起始位置的最大键(floorKey)Integer floorKey = map.floorKey(start);// 如果存在这样的键,且其对应的值大于等于当前起始位置,则可以合并if (floorKey != null && map.get(floorKey) >= start) {start = floorKey;end = Math.max(map.get(floorKey), end);map.remove(floorKey);}// 继续检查后面的区间是否可以合并Integer ceilingKey = map.ceilingKey(start);while (ceilingKey != null && ceilingKey <= end) {end = Math.max(map.get(ceilingKey), end);map.remove(ceilingKey);ceilingKey = map.ceilingKey(start);}// 将合并后的区间加入 TreeMapmap.put(start, end);}// 将 TreeMap 转换为数组int[][] result = new int[map.size()][2];int i = 0;for (Map.Entry<Integer, Integer> entry : map.entrySet()) {result[i][0] = entry.getKey();result[i][1] = entry.getValue();i++;}return result;}
}

5.3 代码详解

TreeMap 法的关键在于利用 TreeMap 的有序性和范围查询功能:

// 使用 TreeMap 来存储区间,键为起始位置,值为结束位置
TreeMap<Integer, Integer> map = new TreeMap<>();
  • TreeMap 自动按键(区间起始位置)排序
  • 值保存区间的结束位置
// 查找小于等于当前起始位置的最大键(floorKey)
Integer floorKey = map.floorKey(start);// 如果存在这样的键,且其对应的值大于等于当前起始位置,则可以合并
if (floorKey != null && map.get(floorKey) >= start) {start = floorKey;end = Math.max(map.get(floorKey), end);map.remove(floorKey);
}
  • floorKey(start) 查找小于等于 start 的最大键
  • 如果该键对应的值大于等于 start,说明区间重叠,需要合并
  • 合并后更新起始位置和结束位置,并从 TreeMap 中移除原区间
// 继续检查后面的区间是否可以合并
Integer ceilingKey = map.ceilingKey(start);
while (ceilingKey != null && ceilingKey <= end) {end = Math.max(map.get(ceilingKey), end);map.remove(ceilingKey);ceilingKey = map.ceilingKey(start);
}
  • ceilingKey(start) 查找大于等于 start 的最小键
  • 循环检查是否有更多区间需要合并
  • 对于每个满足条件的区间,更新结束位置并从 TreeMap 中移除
// 将合并后的区间加入 TreeMap
map.put(start, end);
  • 将最终合并后的区间添加到 TreeMap 中
// 将 TreeMap 转换为数组
int[][] result = new int[map.size()][2];
int i = 0;
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {result[i][0] = entry.getKey();result[i][1] = entry.getValue();i++;
}
  • 将 TreeMap 中的区间转换为要求返回的二维数组

5.4 复杂度分析

  • 时间复杂度: O(n log n),其中 n 是区间的数量。TreeMap 的插入和查找操作需要 O(log n) 时间,最坏情况下我们可能需要对每个区间进行这些操作。
  • 空间复杂度: O(n),需要存储 TreeMap 和结果数组。

5.5 适用场景

TreeMap 法特别适合以下场景:

  • 需要动态添加或删除区间
  • 需要频繁查询与特定点或区间重叠的区间
  • 实现更复杂的区间操作,如求区间交集、差集等

对于本题的静态区间合并问题,第一种解法(排序+一次遍历)通常更为简洁高效。

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

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

6.1 示例 1:基本重叠情况

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]

使用解法一(排序+一次遍历法):

  1. 排序
    输入已按起始位置排序:[[1,3],[2,6],[8,10],[15,18]]

  2. 初始化

    • result = [[1,3]]
    • currentInterval = [1,3]
  3. 遍历

    • 处理 [2,6]

      • 检查:2 <= 3,有重叠
      • 更新 currentInterval[1,6]
      • result = [[1,6]]
    • 处理 [8,10]

      • 检查:8 > 6,无重叠
      • 添加到结果:result = [[1,6],[8,10]]
      • 更新 currentInterval = [8,10]
    • 处理 [15,18]

      • 检查:15 > 10,无重叠
      • 添加到结果:result = [[1,6],[8,10],[15,18]]
      • 更新 currentInterval = [15,18]
  4. 返回结果[[1,6],[8,10],[15,18]]

6.2 示例 2:边界相等的情况

输入:intervals = [[1,4],[4,5]]

使用解法一:

  1. 排序
    输入已按起始位置排序:[[1,4],[4,5]]

  2. 初始化

    • result = [[1,4]]
    • currentInterval = [1,4]
  3. 遍历

    • 处理 [4,5]
      • 检查:4 <= 4,有重叠(边界相等也算重叠)
      • 更新 currentInterval[1,5]
      • result = [[1,5]]
  4. 返回结果[[1,5]]

6.3 示例 3:完全包含的情况

输入:intervals = [[1,10],[2,5],[6,8]]

使用解法一:

  1. 排序
    输入已按起始位置排序:[[1,10],[2,5],[6,8]]

  2. 初始化

    • result = [[1,10]]
    • currentInterval = [1,10]
  3. 遍历

    • 处理 [2,5]

      • 检查:2 <= 10,有重叠(完全被包含)
      • 更新 currentInterval[1,10](实际上没变化)
      • result = [[1,10]]
    • 处理 [6,8]

      • 检查:6 <= 10,有重叠(完全被包含)
      • 更新 currentInterval[1,10](实际上没变化)
      • result = [[1,10]]
  4. 返回结果[[1,10]]

6.4 示例 4:逆序区间

输入:intervals = [[5,8],[3,6],[1,2]]

使用解法一:

  1. 排序
    排序后:[[1,2],[3,6],[5,8]]

  2. 初始化

    • result = [[1,2]]
    • currentInterval = [1,2]
  3. 遍历

    • 处理 [3,6]

      • 检查:3 > 2,无重叠
      • 添加到结果:result = [[1,2],[3,6]]
      • 更新 currentInterval = [3,6]
    • 处理 [5,8]

      • 检查:5 <= 6,有重叠
      • 更新 currentInterval[3,8]
      • result = [[1,2],[3,8]]
  4. 返回结果[[1,2],[3,8]]

7. 常见错误与优化

7.1 常见错误

  1. 忘记排序
    这是最常见的错误。如果忘记按区间起始位置排序,算法将不能正确工作。

    // 错误:直接遍历原始数组
    for (int i = 1; i < intervals.length; i++) {// ...
    }// 正确:先排序再遍历
    Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
    for (int i = 1; i < intervals.length; i++) {// ...
    }
    
  2. 重叠条件判断错误
    区间 [a,b][c,d] 重叠的条件是 a <= d && c <= b,简化后即 a <= d && c <= b
    对于已排序的区间(a <= c),重叠条件可进一步简化为 c <= b

    // 错误:判断条件不正确
    if (interval[0] < currentInterval[1]) { // 不包括边界相等情况// ...
    }// 正确:边界相等也视为重叠
    if (interval[0] <= currentInterval[1]) {// ...
    }
    
  3. 忘记更新结束位置
    合并区间时,需要取两个区间结束位置的最大值。

    // 错误:不更新结束位置
    if (interval[0] <= currentInterval[1]) {// 忘记更新结束位置
    }// 正确:更新结束位置为最大值
    if (interval[0] <= currentInterval[1]) {currentInterval[1] = Math.max(currentInterval[1], interval[1]);
    }
    
  4. 边界情况处理不当
    忘记处理空数组或只有一个区间的情况。

    // 忘记处理边界情况
    public int[][] merge(int[][] intervals) {Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));// ...
    }// 正确处理边界情况
    public int[][] merge(int[][] intervals) {if (intervals == null || intervals.length <= 1) {return intervals;}// ...
    }
    

7.2 性能优化

  1. 预估结果大小
    如果有可能,预先估计结果大小可以避免 ArrayList 的扩容操作。

    // 优化:预估结果大小
    List<int[]> result = new ArrayList<>(intervals.length); // 最多有intervals.length个区间
    
  2. 直接操作数组
    对于特别大的输入,可以考虑直接操作数组而不是使用 ArrayList,以减少内存分配。

    // 优化:直接操作数组
    int[][] result = new int[intervals.length][2];
    int idx = 0;result[idx++] = intervals[0];for (int i = 1; i < intervals.length; i++) {// ...if (overlap) {result[idx-1][1] = Math.max(...);} else {result[idx++] = intervals[i];}
    }// 创建正确大小的结果数组
    return Arrays.copyOf(result, idx);
    
  3. 避免无用合并
    对于明显不可能重叠的区间(例如数据范围很大但区间很少),可以考虑先检查是否有重叠的可能。

    // 优化:检查是否有可能重叠
    int minStart = Integer.MAX_VALUE;
    int maxEnd = Integer.MIN_VALUE;for (int[] interval : intervals) {minStart = Math.min(minStart, interval[0]);maxEnd = Math.max(maxEnd, interval[1]);
    }if (maxEnd - minStart < intervals.length) {// 区间可能重叠,需要合并// ...
    } else {// 区间不可能全部重叠,正常处理// ...
    }
    

8. 扩展题目与应用

8.1 区间插入

LeetCode 57. 插入区间:给你一个无重叠的,按照区间起始端点排序的区间列表,在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠。

解法思路:

  1. 找到新区间应该插入的位置
  2. 处理与新区间重叠的已有区间
  3. 合并所有重叠区间

8.2 区间列表的交集

LeetCode 986. 区间列表的交集:给定两个由一些闭区间组成的列表,每个区间列表都是成对不相交的,并且已经排序。返回这两个区间列表的交集。

解法思路:

  1. 使用双指针分别遍历两个区间列表
  2. 计算当前两个区间的交集
  3. 移动指向结束位置较小的那个区间的指针

8.3 会议室问题

LeetCode 252. 会议室:给定一系列会议时间区间,判断一个人是否能参加所有会议。

LeetCode 253. 会议室 II:给定一系列会议时间区间,计算需要的最少会议室数量。

这类问题本质上也是区间操作问题,可以应用类似的排序和扫描线技术解决。

9. 实际应用场景

区间合并问题在实际应用中非常常见:

  1. 日程安排

    • 查找空闲时间段
    • 合并重叠的会议时间
    • 冲突检测
  2. 资源分配

    • 合并重叠的资源占用时间
    • 最小化所需资源数量
  3. 网络连接管理

    • 合并重叠的网络流量时间段
    • 带宽利用分析
  4. 数据压缩

    • 合并连续的数据块
    • 减少存储需求
  5. 基因序列分析

    • 合并重叠的基因片段
    • 基因组装

10. 完整的 Java 解决方案

以下是结合了各种优化和最佳实践的完整解决方案:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;class Solution {public int[][] merge(int[][] intervals) {// 处理边界情况if (intervals == null) {return new int[0][0];}int n = intervals.length;if (n <= 1) {return intervals;}// 按照区间的起始位置排序Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));// 用于存储合并后的区间List<int[]> result = new ArrayList<>();// 初始化当前区间为第一个区间int start = intervals[0][0];int end = intervals[0][1];// 遍历排序后的区间for (int i = 1; i < n; i++) {// 当前区间int[] current = intervals[i];// 如果当前区间与合并区间重叠if (current[0] <= end) {// 更新合并区间的结束位置end = Math.max(end, current[1]);} else {// 将合并完成的区间加入结果result.add(new int[]{start, end});// 开始新的合并区间start = current[0];end = current[1];}}// 添加最后一个合并区间result.add(new int[]{start, end});// 转换为数组并返回return result.toArray(new int[result.size()][]);}
}

代码已经尽可能简化,同时保持了良好的可读性和正确性。这个解决方案在 LeetCode 上的表现通常会击败约 95% 的提交。

11. 总结与技巧

11.1 解题要点

  1. 排序是关键:区间问题通常需要先排序,使得相似的区间靠在一起。
  2. 一次遍历合并:排序后,只需一次遍历即可合并所有重叠区间。
  3. 重叠条件:理解区间重叠的条件是解决此类问题的基础。
  4. 妥善处理边界情况:包括空输入、单区间输入和边界相等的情况。

11.2 学习收获

通过学习合并区间问题,你可以掌握:

  • 区间操作的基本技巧
  • 贪心算法的应用
  • 排序和扫描线技术
  • 数据结构的选择与性能优化

11.3 面试技巧

如果在面试中遇到此类问题:

  1. 先分析问题,理解重叠的定义
  2. 提出排序的思路,解释为什么排序是必要的
  3. 设计核心算法:如何合并重叠区间
  4. 讨论边界情况和可能的优化
  5. 分析时间和空间复杂度

无论哪种区间问题,排序通常是第一步,之后的具体操作取决于问题要求(合并、插入、查找交集等)。

12. 参考资料

  • LeetCode 官方题解:合并区间
  • LeetCode 题目链接:合并区间

相关文章:

Java详解LeetCode 热题 100(14):LeetCode 56. 合并区间(Merge Intervals)详解

文章目录 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. 解法三&#xff1a;TreeMa…...

回答 | 图形数据库neo4j社区版可以应用小型企业嘛?

刚在知乎上看到了一个提问&#xff0c;挺有意思&#xff0c;于是乎&#xff0c;贴到这里再简聊一二。 转自知乎提问 当然可以&#xff0c;不过成本问题不容小觑。另外还有性能上的考量。 就在最近&#xff0c;米国国家航空航天局——NASA因为人力成本问题&#xff0c;摒弃了使…...

2024年北理工Python123第六章测验题整理

测验题一般不会太难&#xff0c;但是这次的题目&#xff0c;未免太多了&#xff0c;有的还很难 一、选择题 二、编程题 1-10 列表和字符串 1-10都是和列表、字符串有关的题目&#xff0c;都很简单,我直接给出代码了 1.列表排序输出 import random random.seed(int(input()…...

常用的设计模式详解

常用的设计模式详解 在后端开发中&#xff0c;设计模式是提升代码可维护性、扩展性和灵活性的关键工具。通过合理应用设计模式&#xff0c;开发者能够高效解决复杂问题并优化系统架构。本文将结合实际案例&#xff0c;深入探讨后端开发中常用的设计模式及其核心应用场景。 一、…...

OFCMS代码审计-freemaker注入sql注入xxexss文件上传

环境搭建 下载地址&#xff1a;https://gitee.com/oufu/ofcms/repository/archive/V1.1.2?formatzip SSTI模板注入&#xff08;freemaker) FreeMarker模板注入实现远程命令执行 - Eleven_Liu - 博客园 在admin中找到这个 发现请求的是这个 找到他 <#assign value"f…...

python与nodejs哪个性能高

在一般的Web开发和高并发场景中&#xff0c;Node.js的性能通常优于Python&#xff0c;特别是在处理大量异步任务和实时应用时更具优势&#xff1b;而在数据分析、机器学习及计算密集型任务中&#xff0c;Python则表现出更高的性能优势。 Node.js以事件驱动的非阻塞I/O模型著称&…...

云平台管理部署知识点——问题+答案

1、在k8s 中定义副本数量的关键字是那个&#xff1f;处于那个模块下&#xff1f; 关键字&#xff1a;replicas 模块&#xff1a;spec下 2、在k8s中&#xff0c;有状态应用和无状态应用的区别&#xff1f;创建有状态和无状态应用分别使用哪种资源对象类型&#xff1f; &#…...

数据结构(六)——树和二叉树

一、树和二叉树的定义与存储 1.树的定义 树是一种非线性的数据结构&#xff0c;它是由n个有限结点组成有层次关系的集合 树具有以下特点&#xff1a; &#xff08;1&#xff09;每个结点具有0个或多个子结点 &#xff08;2&#xff09;每个子结点只有一个父结点 &#xff…...

基于构件的开发方法与传统开发方法的区别

在软件开发领域,基于构件的开发方法和传统开发方法有着截然不同的特点与应用效果,这些差异显著影响着项目的实施过程与最终成果。下面,我们将从多个关键维度展开对比分析。​ 一、开发模式:线性搭建与模块组装​ 传统开发方法遵循线性的、自顶向下的流程,就像搭建一座高楼…...

cursor对话关键词技巧

提示词基本结构与原则 一个好的 Cursor 提示词通常包含三个部分&#xff1a;目标说明 上下文信息 具体要求。 例如&#xff1a; 创建一个React登录组件&#xff0c;使用Tailwind CSS样式&#xff0c;需要包含邮箱验证功能和记住密码选项。 效果演示&#xff1a; 提示词的的…...

克隆虚拟机组成集群

一、克隆虚拟机 1. 准备基础虚拟机 确保基础虚拟机已安装好操作系统&#xff08;如 Ubuntu&#xff09;、Java 和 Hadoop。关闭防火墙并禁用 SELinux&#xff08;如适用&#xff09;&#xff1a; bash sudo ufw disable # Ubuntu sudo systemctl disable firewalld # CentO…...

添加购物车-02.代码开发

一.代码开发 购物车属于用户端功能&#xff0c;因此要在user下创建controller代码。 Controller层 package com.sky.controller.user;import com.sky.dto.ShoppingCartDTO; import com.sky.entity.ShoppingCart; import com.sky.result.Result; import com.sky.service.Shopp…...

2094. 找出 3 位偶数

from typing import Listclass Solution:def findEvenNumbers(self, digits: List[int]) -> List[int]:# 统计 digits 中每个数字&#xff08;0-9&#xff09;的出现次数。cnt [0] * 10for d in digits:cnt[d] 1ans []# i0 百位&#xff0c;i1 十位&#xff0c;i2 个位&a…...

外出充电不发愁,倍思便携式移动电源成出行新宠

电子设备已深度融入现代快节奏生活&#xff0c;成为出行必备。但随之而来的电量焦虑&#xff0c;却始终困扰着人们。无论是出差远行、户外探索&#xff0c;还是每日通勤&#xff0c;如何随时为设备充电&#xff0c;成了亟待解决的难题。倍思极客充伸缩数据线充电宝应运而生&…...

防火墙安全策略基础配置

拓朴图 设备基础配置 # AR1 路由器配置 [Huawei]interface GigabitEthernet0/0/0 [Huawei-GigabitEthernet0/0/0]ip address 1.1.1.2 255.255.255.0 [Huawei]ip route-static 192.168.1.0 255.255.255.0 1.1.1.1# FW1 防火墙配置 [USG6000V1]sysname FW1 [FW1]interface Gigab…...

系统架构-通信系统架构设计

通信网络系统架构 局域网 单一机构所拥有的专用计算机网络 局域网从早期只提供二层交换功能的简单网络发展到现在&#xff0c;还提供三层路由功能的复杂网络 局域网的典型架构风格&#xff1a; 单核心架构&#xff1a;由一台核心二层或三层交换设备充当网络的核心设备&…...

2.3 定积分

一、数学定义与核心公式 核心思想&#xff1a; 定积分是通过无限细分区间、累加微小矩形面积来逼近曲边图形面积的数学工具。其本质是极限过程下的误差控制与动态平衡。 公式与符号解析&#xff1a; 表达式&#xff1a;定积分写作 ∫ₐᵇ f(x)dx&#xff0c;表示在区间 [a, …...

TCPIP详解 卷1协议 八 ICMPv4和ICMPv6 Internet控制报文协议

8.1——ICMPv4和ICMPv6 Internet控制报文协议 IP 协议本身并没有为终端系统提供直接的方法来发现那些发往目的地址失败的IP数据包。此外&#xff0c;IP 没有提供直接的方式来获取诊断信息&#xff08;例如&#xff0c;哪些路由器在沿途中被使用了或使用一种方法来估计往返时间…...

ik 分词器 设置自定义词典

进入 ES 的安装目录&#xff0c;进入 /elasticsearch-8.10.0/plugins/ik/config/ 文件夹目录&#xff0c;打开 IKAnalyzer.cfg.xml 文件进行配置。 一、添加 自定义扩展词典 扩展词&#xff1a;就是不想哪些词分开&#xff0c;让他们成为一个词&#xff0c;比如“蒙的全是对…...

RabbitMQ 工作模式

RabbitMQ 一共有 7 中工作模式&#xff0c;可以先去官网上了解一下&#xff08;一下截图均来自官网&#xff09;&#xff1a;RabbitMQ 官网 Simple P&#xff1a;生产者&#xff0c;要发送消息的程序&#xff1b;C&#xff1a;消费者&#xff0c;消息的接受者&#xff1b;hell…...

sqlmap使用入门

sqlmap加速了sql注入的发展&#xff0c;需要掌握6点&#xff0c;其一是--dbs获得数据库名称&#xff0c;其二是-D 数据库名称 --tables 获得数据库中的所有表名&#xff0c;其三是-D 数据库名 -T 表名 -C 字段1,字段2 --dump 获得数据库中的表中的字段的值&#xff0c;其四是-r…...

C++23 中的 views::stride:让范围操作更灵活

文章目录 什么是 views::stride语法与用法参数与返回值实现细节适用场景编译器支持总结 什么是 views::stride views::stride 是 C23 引入的一个范围适配器。它允许我们从一个范围中以固定步长提取元素&#xff0c;从而生成一个新的范围视图。具体来说&#xff0c;给定一个范围…...

OSI 7层模型

OSI 7层模型&#xff1a; 1、物理层&#xff08;光纤等把电脑连接起来的物理手段&#xff09; 2、数据链路层&#xff08;以太网&#xff0c;确认0和1电信号的分组方式&#xff0c;负责MAC地址&#xff0c;MAC地址用于在网络中唯一标示一个网卡&#xff0c;相当于网卡的身份证…...

向量组的维度是单个向量中元素的个数

在线性代数中&#xff0c;向量组的维数通常指的是单个向量中元素的个数&#xff0c;即每个向量的维度&#xff08;dimension&#xff09;。例如&#xff0c;一个由三维几何向量&#xff08;如 ( x , y , z ) (x, y, z) (x,y,z)&#xff09;组成的向量组&#xff0c;其维数是3&…...

VM中 ubuntu 网卡不显示

1.添加网卡配置 #sudo nano /etc/netplan/01-netcfg.yaml network:version: 2renderer: networkdethernets:ens33:dhcp4: trueens37:dhcp4: trueens38:dhcp4: true#保存后 sudo netplan apply2.查看网络状态 sudo systemctl start systemd-networkd sudo systemctl status sy…...

Scratch基础-运动模块详解

一、本次任务 二、内容详解 1&#xff09;点位坐标知识 1、什么是坐标&#xff1f; 答&#xff1a; 坐标是定位位置的数字&#xff0c;大家进教室是不是都有自己的座位&#xff1f;比如第3排第2列&#xff1f;这就像Scratch舞台的坐标&#xff0c;每个角色都有自己的‘座位号’…...

dp自动化登陆之hCaptcha 验证码

hCaptcha 是一种常见的验证码服务&#xff0c;用于区分人类用户和自动化程序。由于其基于图像识别和行为分析&#xff0c;下面介绍如何使用自动化点击验证码完成登陆。 思路&#xff1a;登陆目标网站触发验证码&#xff0c;截图并发给打码平台返回坐标&#xff0c;模拟人工点击…...

【002】renPy android端启动流程分析

接上篇分析 org.renpy.android.PythonSDLActivity#onCreate它先调用了 org.libsdl.app.SDLActivity#onCreate 源码如下&#xff1a; Override // android.app.Activity protected void onCreate(Bundle bundle0) {//1. 日志记录String s;Log.v("SDL", "Dev…...

基于注意力机制与iRMB模块的YOLOv11改进模型—高效轻量目标检测新范式

随着深度学习技术的发展&#xff0c;目标检测在自动驾驶、智能监控、工业质检等场景中得到了广泛应用。针对当前主流目标检测模型在边缘设备部署中所面临的计算资源受限和推理效率瓶颈问题&#xff0c;YOLO系列作为单阶段目标检测框架的代表&#xff0c;凭借其高精度与高速度的…...

suricata增加单元测试编译失败

一、环境 $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.5 LTS Release: 22.04 Codename: jammysuricata: suricata7.0.5 IDE: vscode 二、背景 在suricata中开发了某个功能后&#xff0c;增加unittest时&#xff0c;…...

如何查看电脑处理器配置 电脑处理器查看方法

电脑处理器&#xff08;CPU&#xff09;直接影响着电脑的运行速度和响应能力&#xff0c;无论是进行日常办公、娱乐&#xff0c;还是玩大型游戏&#xff0c;处理器的性能都至关重要。那么&#xff0c;电脑cpu在哪里看呢&#xff1f;本文将为你介绍几种简单的方法&#xff0c;帮…...

idea查看pom文件依赖

IDEA中查看依赖树的插件 很方便 能够分析源码中引入的注解是来自哪个jar包的...

图形化编程平台的破局之道:从工具同质化到生态差异化

一、同质化困局的底层逻辑剖析 在全球图形化编程市场中&#xff0c;工具功能趋同已成为行业共识。据 Statista 2024 年数据显示&#xff0c;主流平台的基础功能重合度高达 78%&#xff0c;核心模块&#xff08;如条件判断、循环结构&#xff09;的实现方式高度相似。这种现象的…...

Spring Boot动态配置修改全攻略

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 无需重启应用&#xff0c;实时更新配置的终极指南 在微服务架构中&#xff0c;动态配置管理是提高系统灵活性的关键技术。本文将通过4种主流方案&#xff0c…...

基于STM32、HAL库的DPS368XTSA1气压传感器 驱动程序设计

一、简介: DPS368XTSA1 是 InvenSense(TDK 集团旗下公司)生产的一款高精度数字气压传感器,专为需要精确测量气压和温度的应用场景设计。它具有超低功耗、高精度、快速响应等特点,非常适合物联网、可穿戴设备和无人机等应用。 二、硬件接口: DPS368XTSA1 引脚STM32L4XX 引…...

VMware虚拟机实例-docker启动失败

DOCKER启动失败 错误消息 [rootlocalhost docker]# yum install docker......[rootlocalhost docker]# systemctl start dockerFailed to start docker.service: Unit is masked. 错误原因 # /var/log/messagesMay 12 18:14:04 localhost systemd: Started Session 11 of user…...

计算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 09.天空和背景

天空和背景 对于 3D 场景&#xff0c;通常可以通过在远处的地平线附近创造一些逼真的效果&#xff0c;来增强其真实感。我们可以采用天空盒、天空柱&#xff08;Skydome&#xff09;或天空穹&#xff08;Skydome&#xff09;等技术来模拟天空。 天空盒 天空盒&#xff08;Sk…...

CSDN博客粘贴图片失败如何解决

以前还好&#xff0c;最近越发的厉害了。 因为我最近恰好换了个网&#xff0c;所以我还以为是网络的问题。 网的问题我暂时解决不了&#xff0c;除非在加银子换个网&#xff0c;否则我搞不定。 终于找到一种貌似还行的方法&#xff0c;记录一下。 1&#xff0c;现象 CSDN博…...

USB学习【10】描述符-HID描述符

目录 1.前言2.HID描述符概述3.HID描述符组成4.报告描述符的概念和作用5.报告描述符中的通用项&#xff08;Item&#xff09; 1.前言 HID描述符功能上面相对独立一些&#xff0c;所以单分一篇专门整理。 原文链接&#xff1a;https://blog.csdn.net/weiaipan1314/article/detai…...

什么是Vim

Vim可是Linux中最强大、最受欢迎的文本编辑器之一&#xff0c;很多程序员、系统管理员都离不开它。要说清楚Vim的各种功能和用法&#xff0c;似乎有点长&#xff0c;但我会尽量用简单通俗的方式&#xff0c;把Vim的核心知识讲清楚&#xff0c;让你能一步一步开始使用它。 一、…...

【Unity3D插件】Unity3D插件之天气系统/日夜系统插件-UniStorm

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享QQ群&#xff1a;398291828小红书小破站 一、前言 1.0136537.8&#xff0c;1.023651377.4&#xff0c;每天进步一点点&#xff0c;一年后就差了几十倍的差距&#xff0c;加油吧少年。 UniStorm是一款强大的动态昼夜天气系统&…...

AIGC时代的内容安全:AI检测技术如何应对新型风险挑战?

在数字时代&#xff0c;互联网内容以文本、图像、音频和视频等形式呈现爆发式增长&#xff0c;深刻塑造了信息传播的格局。然而&#xff0c;内容的快速传播也带来了严峻挑战&#xff1a;违法信息&#xff08;如涉黄、涉政&#xff09;、虚假广告、网络暴力等内容不仅威胁用户体…...

SAGAR线上网页程序生成准随机结构(SQS)

SAGAR线上网页程序地址 http://sagar.compphys.cn/sagar 页面最上方默认使用8个原子的Si为基础结构。 打开网页 选择C1模块 在下方填入结构信息&#xff0c;以及掺杂入原子和数量 这里则设置掺杂入4个C原子&#xff0c;然后点击submit&#xff0c;则会自动生成并让你下载一根压…...

Wi-Fi网络角色及功能详解

在 Wi-Fi 网络中&#xff0c;不同的角色和组件协同工作以实现无线通信。以下是 Wi-Fi 中的主要角色及其功能&#xff1a; 1. 基础设施模式&#xff08;Infrastructure Mode&#xff09; 这是最常见的 Wi-Fi 网络架构&#xff0c;包含以下核心角色&#xff1a; 接入点&#xff…...

18.three官方示例+编辑器+AI快速学习webgl_buffergeometry_points_interleaved

本实例主要讲解内容 这个Three.js示例展示了如何使用BufferGeometry和Points对象创建高效的粒子系统。通过共享内存缓冲区和交错存储顶点数据&#xff0c;实现了50万个粒子的流畅渲染&#xff0c;并为每个粒子设置基于位置的颜色。 核心技术包括&#xff1a; 使用ArrayBuffe…...

Oracle 19c 静默安装

文章目录 环境介绍安装包下载准备工作配置 yum 源安装依赖包创建用户和用户组创建必要目录关闭 SELinux配置内核参数配置资源限制配置环境变量 Oracle 19c 安装解压缩编辑相应文件执行静默安装配置监听静默创建数据库 数据库维护连接数据库 环境介绍 操作系统为 CentOS 7.9 O…...

vscode 默认环境路径

1.下面放在项目根目录上&#xff1a; .vscode/settings.json 2.settings.json内容&#xff1a; {"python.analysis.extraPaths": ["${workspaceFolder}"],"python.defaultInterpreterPath": "/shared_disk/users/lbg/envs/py310_see3d/b…...

电力系统静态安全因素与动态安全因素的区别及具体分类

电力系统的安全分析分为静态安全和动态安全两类。静态安全分析关注系统在稳态或小扰动下的安全裕度&#xff0c;动态安全分析则关注系统在大扰动或暂态过程中的稳定能力。 一、静态安全因素 频率静态安全 因素&#xff1a; 发电与负荷的静态平衡&#xff1a;需保证稳态下的发电…...

arduinoIDE核心库更新导致的ESP32开发板神秘接口更换和三方库冲突

ESP32开发遇到的问题的解决记录贴 arduinoIDE核心库更新导致的ESP32开发板神秘接口更换和三方库冲突情况描述其余解决方法&#xff08;网上查的&#xff0c;未验证&#xff09;&#xff1a; arduinoIDE核心库更新导致的ESP32开发板神秘接口更换和三方库冲突 情况描述 当我将a…...

MCU开启浮点计算FPU

FPU 测试 1. FPU 简介2. 协处理器控制寄存器&#xff08;CPACR&#xff09;3. 开启FPU4. 验证FPU&#xff08;Julia 分形实验&#xff09; 1. FPU 简介 FPU 即浮点运算单元&#xff08;Float Point Unit&#xff09;。浮点运算&#xff0c;对于定点 CPU&#xff08;没有 FPU 的…...