算法刷题记录——LeetCode篇(9.1) [第801~810题]
更新时间:2025-03-29
- 算法题解目录汇总:算法刷题记录——题解目录汇总
- 技术博客总目录:计算机技术系列博客——目录页
优先整理热门100及面试150,不定期持续更新,欢迎关注!
801. 使序列递增的最小交换次数
我们有两个长度相等且不为空的整型数组 nums1
和 nums2
。在一次操作中,我们可以交换 nums1[i]
和 nums2[i]
的元素。
例如,如果 nums1 = [1,2,3,8]
, nums2 =[5,6,7,4]
,你可以交换 i = 3
处的元素,得到 nums1 =[1,2,3,4]
和 nums2 =[5,6,7,8]
。
返回 使 nums1
和 nums2
严格递增 所需操作的最小次数 。
数组 arr
严格递增 且 arr[0] < arr[1] < arr[2] < ... < arr[arr.length - 1]
。
注意:
用例保证可以实现操作。
示例 1:
输入: nums1 = [1,3,5,4], nums2 = [1,2,3,7]
输出: 1
解释:
交换 A[3] 和 B[3] 后,两个数组如下:
A = [1, 3, 5, 7] , B = [1, 2, 3, 4]
两个数组均为严格递增的。
示例 2:
输入: nums1 = [0,3,5,8,9], nums2 = [2,1,4,6,9]
输出: 1
提示:
2 <= nums1.length <= 10^5
nums2.length == nums1.length
0 <= nums1[i], nums2[i] <= 2 * 10^5
方法:动态规划
使用动态规划来维护两个状态:swap
表示在第 i
个位置交换元素所需的最小交换次数,noswap
表示不交换时的最小交换次数。
通过遍历数组,检查每个位置是否可以从前一个位置的两种状态(交换或不交换)转移而来,并更新当前状态。
- 初始化:初始时,
swap
为 1(交换第一个元素),noswap
为 0(不交换第一个元素)。 - 遍历数组:从第二个元素开始,遍历每个位置
i
。 - 状态转移:
- 检查是否可以从
i-1
不交换的状态转移而来:- 不交换当前元素的条件:
nums1[i] > nums1[i-1]
且nums2[i] > nums2[i-1]
。 - 交换当前元素的条件:
nums2[i] > nums1[i-1]
且nums1[i] > nums2[i-1]
。
- 不交换当前元素的条件:
- 检查是否可以从
i-1
交换的状态转移而来:- 不交换当前元素的条件:
nums1[i] > nums2[i-1]
且nums2[i] > nums1[i-1]
。 - 交换当前元素的条件:
nums2[i] > nums2[i-1]
且nums1[i] > nums1[i-1]
。
- 不交换当前元素的条件:
- 检查是否可以从
- 更新状态:根据上述条件,更新当前
swap
和noswap
的值。 - 返回结果:遍历结束后,返回
swap
和noswap
中的最小值。
代码实现(Java):
class Solution {public int minSwap(int[] nums1, int[] nums2) {int n = nums1.length;int swap = 1, noswap = 0;for (int i = 1; i < n; i++) {int newSwap = Integer.MAX_VALUE;int newNoswap = Integer.MAX_VALUE;// 检查是否可以从i-1不交换转移而来if (nums1[i] > nums1[i-1] && nums2[i] > nums2[i-1]) {newNoswap = Math.min(newNoswap, noswap);}if (nums2[i] > nums1[i-1] && nums1[i] > nums2[i-1]) {newSwap = Math.min(newSwap, noswap + 1);}// 检查是否可以从i-1交换转移而来if (nums1[i] > nums2[i-1] && nums2[i] > nums1[i-1]) {newNoswap = Math.min(newNoswap, swap);}if (nums2[i] > nums2[i-1] && nums1[i] > nums1[i-1]) {newSwap = Math.min(newSwap, swap + 1);}swap = newSwap;noswap = newNoswap;}return Math.min(swap, noswap);}
}
复杂度分析
- 时间复杂度:O(n),遍历数组一次。
- 空间复杂度:O(1),仅使用常量空间维护两个状态变量。
802. 找到最终的安全状态
有一个有 n
个节点的有向图,节点按 0
到 n - 1
编号。图由一个 索引从 0
开始的 2D 整数数组 graph
表示, graph[i]
是与节点 i
相邻的节点的整数数组,这意味着从节点 i
到 graph[i]
中的每个节点都有一条边。
如果一个节点没有连出的有向边,则该节点是 终端节点 。如果从该节点开始的所有可能路径都通向 终端节点 ,则该节点为 安全节点 。
返回一个由图中所有 安全节点 组成的数组作为答案。答案数组中的元素应当按 升序 排列。
示例 1:
输入:graph = [[1,2],[2,3],[5],[0],[5],[],[]]
输出:[2,4,5,6]
解释:
节点 5 和节点 6 是终端节点,因为它们都没有出边。
从节点 2、4、5 和 6 开始的所有路径都指向节点 5 或 6 。
示例 2:
输入:graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]]
输出:[4]
解释:
只有节点 4 是终端节点,从节点 4 开始的所有路径都通向节点 4 。
提示:
n == graph.length
1 <= n <= 10^4
0 <= graph[i].length <= n
0 <= graph[i][j] <= n - 1
graph[i] 按严格递增顺序排列
图中可能包含自环
图中边的数目在范围 [1, 4 * 10^4] 内
方法:拓扑排序(出度处理)
安全节点的条件是其所有路径最终都到达终端节点(无出边或路径无环)。通过拓扑排序,从终端节点(出度为0)开始,反向处理所有指向它们的节点,逐步将出度减为0的节点标记为安全。
- 构建反向图:记录每个节点被哪些节点指向。
- 计算初始出度:每个节点的出边数目。
- 初始化队列:将出度为0的节点加入队列并标记为安全。
- 拓扑排序处理:从队列取出节点,更新其反向图中前驱节点的出度,若减至0则加入队列并标记安全。
- 收集结果:所有标记为安全的节点排序后输出。
代码实现(Java):
class Solution {public List<Integer> eventualSafeNodes(int[][] graph) {int n = graph.length;List<List<Integer>> reverseGraph = new ArrayList<>();for (int i = 0; i < n; i++) {reverseGraph.add(new ArrayList<>());}for (int v = 0; v < n; v++) {for (int u : graph[v]) {reverseGraph.get(u).add(v);}}int[] outDegree = new int[n];for (int i = 0; i < n; i++) {outDegree[i] = graph[i].length;}Queue<Integer> queue = new LinkedList<>();boolean[] safe = new boolean[n];for (int i = 0; i < n; i++) {if (outDegree[i] == 0) {queue.offer(i);safe[i] = true;}}while (!queue.isEmpty()) {int u = queue.poll();for (int v : reverseGraph.get(u)) {outDegree[v]--;if (outDegree[v] == 0) {queue.offer(v);safe[v] = true;}}}List<Integer> result = new ArrayList<>();for (int i = 0; i < n; i++) {if (safe[i]) {result.add(i);}}Collections.sort(result);return result;}
}
复杂度分析
- 时间复杂度:O(n + e),构建反向图和处理队列各需线性时间。
- 空间复杂度:O(n + e),存储反向图和队列所需空间。
803. 打砖块
有一个 m x n
的二元网格 grid
,其中 1
表示砖块,0
表示空白。砖块 稳定(不会掉落)的前提是:
- 一块砖直接连接到网格的顶部,或者
- 至少有一块相邻(4 个方向之一)砖块 稳定 不会掉落时
给你一个数组 hits
,这是需要依次消除砖块的位置。每当消除 hits[i] = (rowi, coli)
位置上的砖块时,对应位置的砖块(若存在)会消失,然后其他的砖块可能因为这一消除操作而 掉落 。一旦砖块掉落,它会 立即 从网格 grid
中消失(即,它不会落在其他稳定的砖块上)。
返回一个数组 result
,其中 result[i]
表示第 i
次消除操作对应掉落的砖块数目。
注意,消除可能指向是没有砖块的空白位置,如果发生这种情况,则没有砖块掉落。
示例 1:
输入:grid = [[1,0,0,0],[1,1,1,0]], hits = [[1,0]]
输出:[2]
解释:
网格开始为:[[1,0,0,0], [1,1,1,0]]
消除 (1,0) 处加粗的砖块,得到网格:[[1,0,0,0] [0,1,1,0]]
两个加粗的砖不再稳定,因为它们不再与顶部相连,也不再与另一个稳定的砖相邻,因此它们将掉落。得到网格:[[1,0,0,0], [0,0,0,0]]
因此,结果为 [2] 。
示例 2:
输入:grid = [[1,0,0,0],[1,1,0,0]], hits = [[1,1],[1,0]]
输出:[0,0]
解释:
网格开始为:[[1,0,0,0], [1,1,0,0]]
消除 (1,1) 处加粗的砖块,得到网格:[[1,0,0,0], [1,0,0,0]]
剩下的砖都很稳定,所以不会掉落。网格保持不变:[[1,0,0,0], [1,0,0,0]]
接下来消除 (1,0) 处加粗的砖块,得到网格:[[1,0,0,0], [0,0,0,0]]
剩下的砖块仍然是稳定的,所以不会有砖块掉落。
因此,结果为 [0,0] 。
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 200
grid[i][j] 为 0 或 1
1 <= hits.length <= 4 * 10^4
hits[i].length == 2
0 <= xi <= m - 1
0 <= yi <= n - 1
所有 (xi, yi) 互不相同
方法:逆向并查集
逆向处理敲击操作,将问题转换为逐步添加砖块。使用并查集维护连通性,并统计每次添加后连接到顶部的砖块数目变化。通过比较添加前后的尺寸变化,计算掉落的砖块数。
- 预处理:复制原网格并移除所有被敲击的砖块。
- 初始化并查集:将预处理后的网格中所有砖块合并,顶部砖块连接到虚拟节点。
- 逆序处理敲击:从最后一次敲击开始,逐步恢复砖块,合并相邻砖块,并计算每次恢复后连接到顶部的砖块数目变化。
- 计算结果:变化量即为当前敲击导致的掉落数目。
代码实现(Java):
class Solution {public int[] hitBricks(int[][] grid, int[][] hits) {int m = grid.length;int n = grid[0].length;int[][] copy = new int[m][n];for (int i = 0; i < m; i++) {System.arraycopy(grid[i], 0, copy[i], 0, n);}// 预处理,移除所有被敲击的砖块for (int[] hit : hits) {int x = hit[0], y = hit[1];if (copy[x][y] == 1) copy[x][y] = 0;}int size = m * n;UnionFind uf = new UnionFind(size + 1);// 初始化顶部砖块连接到虚拟节点for (int j = 0; j < n; j++) {if (copy[0][j] == 1) {uf.union(j, size);}}// 构建初始连通性for (int i = 1; i < m; i++) {for (int j = 0; j < n; j++) {if (copy[i][j] == 1) {// 上方有砖块则合并if (copy[i-1][j] == 1) {uf.union(i * n + j, (i-1) * n + j);}// 左方有砖块则合并if (j > 0 && copy[i][j-1] == 1) {uf.union(i * n + j, i * n + j - 1);}}}}int[] ans = new int[hits.length];int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};// 逆序恢复砖块for (int i = hits.length - 1; i >= 0; i--) {int x = hits[i][0], y = hits[i][1];if (grid[x][y] == 0) {ans[i] = 0;continue;}copy[x][y] = 1;int original = uf.getSize(size);// 若当前砖块在顶部,连接到虚拟节点if (x == 0) {uf.union(x * n + y, size);}// 合并相邻砖块for (int[] d : dirs) {int nx = x + d[0], ny = y + d[1];if (nx >= 0 && nx < m && ny >= 0 && ny < n && copy[nx][ny] == 1) {uf.union(x * n + y, nx * n + ny);}}int current = uf.getSize(size);ans[i] = Math.max(current - original - 1, 0);}return ans;}class UnionFind {private int[] parent;private int[] size;public UnionFind(int n) {parent = new int[n];size = new int[n];for (int i = 0; i < n; i++) {parent[i] = i;size[i] = 1;}}public int find(int x) {if (parent[x] != x) {parent[x] = find(parent[x]);}return parent[x];}public void union(int x, int y) {int rootX = find(x);int rootY = find(y);if (rootX == rootY) return;if (rootX == parent.length - 1) {parent[rootY] = rootX;size[rootX] += size[rootY];} else {parent[rootX] = rootY;size[rootY] += size[rootX];}}public int getSize(int x) {int root = find(x);return root == parent.length - 1 ? size[root] : 0;}}
}
复杂度分析
- 时间复杂度:O(N + K),其中 N 是网格中的元素总数,K 是敲击次数。预处理和并查集操作均接近线性。
- 空间复杂度:O(N),用于存储并查集结构。
804. 唯一摩尔斯密码词
国际摩尔斯密码定义一种标准编码方式,将每个字母对应于一个由一系列点和短线组成的字符串, 比如:
'a' 对应 ".-"
,'b' 对应 "-..."
,'c' 对应 "-.-."
,以此类推。
为了方便,所有 26 个英文字母的摩尔斯密码表如下:
[".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."]
给你一个字符串数组 words
,每个单词可以写成每个字母对应摩尔斯密码的组合。
例如,"cab"
可以写成 "-.-..--..."
,(即 "-.-." + ".-" + "-..."
字符串的结合)。我们将这样一个连接过程称作 单词翻译 。
对 words
中所有单词进行单词翻译,返回不同 单词翻译 的数量。
示例 1:
输入: words = ["gin", "zen", "gig", "msg"]
输出: 2
解释:
各单词翻译如下:
“gin” -> “–…-.”
“zen” -> “–…-.”
“gig” -> “–…–.”
“msg” -> “–…–.”
共有 2 种不同翻译, “–…-.” 和 “–…–.”。
示例 2:
输入:words = ["a"]
输出:1
提示:
1 <= words.length <= 100
1 <= words[i].length <= 12
words[i] 由小写英文字母组成
方法:哈希集合
将每个单词转换为对应的摩尔斯密码字符串,利用哈希集合自动去重的特性统计不同密码的数量。摩尔斯密码表预先存储每个字母的对应编码。
- 初始化摩尔斯密码表:按顺序存储26个字母对应的密码。
- 转换每个单词:遍历单词中的每个字符,拼接对应的摩尔斯密码。
- 使用哈希集合去重:将转换后的字符串存入集合,集合大小即为答案。
代码实现(Java):
class Solution {public int uniqueMorseRepresentations(String[] words) {String[] morseCodes = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};Set<String> uniqueMorse = new HashSet<>();for (String word : words) {StringBuilder sb = new StringBuilder();for (char c : word.toCharArray()) {sb.append(morseCodes[c - 'a']);}uniqueMorse.add(sb.toString());}return uniqueMorse.size();}
}
复杂度分析
- 时间复杂度:O(N*L),其中 N 是单词数量,L 是单词平均长度。每个字符处理时间为常数。
- 空间复杂度:O(N*L),哈希集合存储所有不同的摩尔斯密码字符串。
805. 数组的均值分割
给定你一个整数数组 nums
,我们要将 nums
数组中的每个元素移动到 A
数组 或者 B
数组中,使得 A
数组和 B
数组不为空,并且 average(A) == average(B)
。
如果可以完成则返回true
, 否则返回 false
。
注意: 对于数组 arr
, average(arr)
是 arr
的所有元素的和除以 arr
长度。
示例 1:
输入: nums = [1,2,3,4,5,6,7,8]
输出: true
解释: 我们可以将数组分割为 [1,4,5,8] 和 [2,3,6,7], 他们的平均值都是4.5。
示例 2:
输入: nums = [3,1]
输出: false
提示:
1 <= nums.length <= 30
0 <= nums[i] <= 10^4
方法:折半搜索
将数组分成两部分,分别生成所有可能子集的元素数目和总和。对于每个可能的子集长度k,检查是否存在两部分子集的总和之和等于目标值,从而判断是否可以将数组分割成两个平均值相等的非空子集。
- 计算总和:确定整个数组的总和。
- 分割数组:将数组分成两个部分,减少计算量。
- 生成子集信息:对每个部分生成所有可能子集的元素数目和总和的映射。
- 遍历可能的k:检查每个k是否满足条件,利用两部分的映射快速查询。
代码实现(Java):
class Solution {public boolean splitArraySameAverage(int[] nums) {int n = nums.length;if (n == 1) return false;int totalSum = Arrays.stream(nums).sum();int lenA = n / 2, lenB = n - lenA;int[] A = Arrays.copyOfRange(nums, 0, lenA);int[] B = Arrays.copyOfRange(nums, lenA, n);Map<Integer, Set<Integer>> mapA = generateSubsetSums(A);Map<Integer, Set<Integer>> mapB = generateSubsetSums(B);for (int k = 1; k < n; k++) {if ((totalSum * k) % n != 0) continue;int target = (totalSum * k) / n;for (int a = Math.max(0, k - lenB); a <= Math.min(k, lenA); a++) {int b = k - a;if (!mapA.containsKey(a) || !mapB.containsKey(b)) continue;Set<Integer> sumsA = mapA.get(a);Set<Integer> sumsB = mapB.get(b);for (int sumA : sumsA) {if (sumsB.contains(target - sumA)) return true;}}}return false;}private Map<Integer, Set<Integer>> generateSubsetSums(int[] arr) {Map<Integer, Set<Integer>> map = new HashMap<>();int n = arr.length;for (int mask = 0; mask < (1 << n); mask++) {int bits = Integer.bitCount(mask);int sum = 0;for (int i = 0; i < n; i++) {if ((mask & (1 << i)) != 0) sum += arr[i];}map.computeIfAbsent(bits, k -> new HashSet<>()).add(sum);}return map;}
}
复杂度分析
- 时间复杂度:预处理部分为 O(2^(n/2) * n),查询部分为 O(n^2 * 2^(n/2)),整体在 n=30 时可行。
- 空间复杂度:O(2^(n/2) * n),存储各子集的总和。
806. 写字符串需要的行数
我们要把给定的字符串 S
从左到右写到每一行上,每一行的最大宽度为100个单位,如果我们在写某个字母的时候会使这行超过了100 个单位,那么我们应该把这个字母写到下一行。我们给定了一个数组 widths
,这个数组 widths[0]
代表 'a'
需要的单位, widths[1]
代表 'b'
需要的单位,…, widths[25]
代表 'z'
需要的单位。
**现在回答两个问题:**至少多少行能放下S
,以及最后一行使用的宽度是多少个单位?将你的答案作为长度为2的整数列表返回。
示例 1:
输入:
widths = [10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]
S = "abcdefghijklmnopqrstuvwxyz"
输出: [3, 60]
解释:
所有的字符拥有相同的占用单位10。所以书写所有的26个字母,
我们需要2个整行和占用60个单位的一行。
示例 2:
输入:
widths = [4,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]
S = "bbbcccdddaaa"
输出: [2, 4]
解释:
除去字母’a’所有的字符都是相同的单位10,并且字符串 “bbbcccdddaa” 将会覆盖 9 * 10 + 2 * 4 = 98 个单位.
最后一个字母 ‘a’ 将会被写到第二行,因为第一行只剩下2个单位了。
所以,这个答案是2行,第二行有4个单位宽度。
注:
字符串 S 的长度在 [1, 1000] 的范围。
S 只包含小写字母。
widths 是长度为 26的数组。
widths[i] 值的范围在 [2, 10]。
方法:逐字符遍历
遍历字符串中的每个字符,逐字符计算当前行的宽度。当当前行无法容纳下一个字符时,换行并重置当前行的宽度。最后统计总行数和最后一行的宽度。
- 初始化变量:行数
lines
初始为1,当前行宽度currentWidth
初始为0。 - 遍历每个字符:对于每个字符,获取对应的摩尔斯密码宽度。
- 判断换行:如果当前行加上该字符的宽度超过100,则换行,否则累加宽度。
- 返回结果:最终返回行数和最后一行的宽度。
代码实现(Java):
class Solution {public int[] numberOfLines(int[] widths, String s) {int lines = 1;int currentWidth = 0;for (char c : s.toCharArray()) {int w = widths[c - 'a'];if (currentWidth + w > 100) {lines++;currentWidth = w;} else {currentWidth += w;}}return new int[]{lines, currentWidth};}
}
复杂度分析
- 时间复杂度:O(n),其中 n 是字符串的长度。每个字符处理一次。
- 空间复杂度:O(1),仅使用常数额外空间。
807. 保持城市天际线
给你一座由 n x n
个街区组成的城市,每个街区都包含一座立方体建筑。给你一个下标从 0 开始的 n x n
整数矩阵 grid
,其中 grid[r][c]
表示坐落于 r 行 c 列的建筑物的 高度 。
城市的 天际线 是从远处观察城市时,所有建筑物形成的外部轮廓。从东、南、西、北四个主要方向观测到的 天际线 可能不同。
我们被允许为 任意数量的建筑物 的高度增加 任意增量(不同建筑物的增量可能不同) 。 高度为 0 的建筑物的高度也可以增加。然而,增加的建筑物高度 不能影响
从任何主要方向观察城市得到的 天际线 。
在 不改变 从任何主要方向观测到的城市 天际线 的前提下,返回建筑物可以增加的 最大高度增量总和 。
示例 1:
输入:grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]
输出:35
解释:
用红色绘制从不同方向观看得到的天际线。
在不影响天际线的情况下,增加建筑物的高度:
gridNew = [ [8, 4, 8, 7], [7, 4, 7, 7], [9, 4, 8, 7], [3, 3, 3, 3] ]
示例 2:
输入:grid = [[0,0,0],[0,0,0],[0,0,0]]
输出:0
解释:增加任何建筑物的高度都会导致天际线的变化。
提示:
n == grid.length
n == grid[r].length
2 <= n <= 50
0 <= grid[r][c] <= 100
方法:行列最大值约束
每个建筑物的高度增量受其所在行和列的最大高度限制。新高度不能超过行和列最大值中的较小值,以保持天际线不变。总增量即为所有建筑物允许增加的高度之和。
- 计算行最大值:遍历每行,记录每行的最大值。
- 计算列最大值:遍历每列,记录每列的最大值。
- 计算总增量:对于每个建筑物,其允许的最大高度为行和列最大值的较小者,累计其与原高度的差值。
代码实现(Java):
class Solution {public int maxIncreaseKeepingSkyline(int[][] grid) {int n = grid.length;int[] rowMax = new int[n];int[] colMax = new int[n];// 计算每行的最大值for (int r = 0; r < n; r++) {int max = 0;for (int c = 0; c < n; c++) {max = Math.max(max, grid[r][c]);}rowMax[r] = max;}// 计算每列的最大值for (int c = 0; c < n; c++) {int max = 0;for (int r = 0; r < n; r++) {max = Math.max(max, grid[r][c]);}colMax[c] = max;}// 计算总增量int sum = 0;for (int r = 0; r < n; r++) {for (int c = 0; c < n; c++) {int limit = Math.min(rowMax[r], colMax[c]);sum += limit - grid[r][c];}}return sum;}
}
复杂度分析
- 时间复杂度:O(n²),遍历矩阵三次:计算行最大值、列最大值和总增量,每次均为O(n²)。
- 空间复杂度:O(n),存储行和列的最大值,各需O(n)空间。
808. 分汤
有 A 和 B 两种类型 的汤。一开始每种类型的汤有 n
毫升。有四种分配操作:
- 提供 100ml 的 汤A 和 0ml 的 汤B 。
- 提供 75ml 的 汤A 和 25ml 的 汤B 。
- 提供 50ml 的 汤A 和 50ml 的 汤B 。
- 提供 25ml 的 汤A 和 75ml 的 汤B 。
当我们把汤分配给某人之后,汤就没有了。每个回合,我们将从四种概率同为 0.25 的操作中进行分配选择。如果汤的剩余量不足以完成某次操作,我们将尽可能分配。当两种类型的汤都分配完时,停止操作。
注意:不存在先分配 100 ml 汤B 的操作。
需要返回的值: 汤A 先分配完的概率 + 汤A和汤B 同时分配完的概率 / 2
。返回值在正确答案 10-5
的范围内将被认为是正确的。
示例 1:
输入: n = 50
输出: 0.62500
解释:
- 如果我们选择前两个操作,A 首先将变为空。
- 对于第三个操作,A 和 B 会同时变为空。
- 对于第四个操作,B 首先将变为空。
- 所以 A 变为空的总概率加上 A 和 B 同时变为空的概率的一半是 0.25 *(1 + 1 + 0.5 + 0)= 0.625。
示例 2:
输入: n = 100
输出: 0.71875
提示:
0 <= n <= 10^9
方法:动态规划
当汤的剩余量较大时,每次操作平均消耗的汤A比汤B多,因此汤A更可能先耗尽。通过数学分析,当n≥4800时,结果趋近于1。对于较小的n,使用动态规划计算所有可能状态的转移概率。
- 阈值处理:当n≥4800时,直接返回1.0。
- 单位转换:将汤量转换为25ml的单位,减少状态数目。
- 动态规划:按自底向上方式计算每个状态的转移概率。
代码实现(Java):
class Solution {public double soupServings(int n) {if (n == 0) return 0.5;if (n >= 4800) return 1.0;int m = (n + 24) / 25; // 转换为25ml单位,向上取整double[][] dp = new double[m + 1][m + 1];for (int a = 0; a <= m; a++) {for (int b = 0; b <= m; b++) {int realA = a * 25;int realB = b * 25;if (realA > n) realA = n;if (realB > n) realB = n;if (realA == 0 && realB == 0) {dp[a][b] = 0.5;} else if (realA == 0) {dp[a][b] = 1.0;} else if (realB == 0) {dp[a][b] = 0.0;} else {// 处理四种操作int[][] ops = {{4, 0}, {3, 1}, {2, 2}, {1, 3}};double sum = 0.0;for (int[] op : ops) {int newA = a - op[0];int newB = b - op[1];newA = Math.max(newA, 0);newB = Math.max(newB, 0);if (newA >= dp.length) newA = dp.length - 1;if (newB >= dp[0].length) newB = dp[0].length - 1;sum += dp[newA][newB];}dp[a][b] = sum * 0.25;}}}return dp[m][m];}
}
复杂度分析
- 时间复杂度:O(m²),其中m = n/25。对于较小的n,m最多为192(当n=4800时),时间复杂度可接受。
- 空间复杂度:O(m²),存储动态规划表。
809. 情感丰富的文字
有时候人们会用重复写一些字母来表示额外的感受,比如 "hello" -> "heeellooo"
, "hi" -> "hiii"
。我们将相邻字母都相同的一串字符定义为相同字母组,例如:"h"
, "eee"
, "ll"
, "ooo"
。
对于一个给定的字符串 S
,如果另一个单词能够通过将一些字母组扩张从而使其和 S
相同,我们将这个单词定义为可扩张的(stretchy)。扩张操作定义如下:选择一个字母组(包含字母 c
),然后往其中添加相同的字母 c
使其长度达到 3 或以上。
例如,以 "hello"
为例,我们可以对字母组 "o"
扩张得到 "hellooo"
,但是无法以同样的方法得到 "helloo"
因为字母组 "oo"
长度小于 3。此外,我们可以进行另一种扩张 "ll" -> "lllll"
以获得 "helllllooo"
。如果 s = "helllllooo"
,那么查询词 "hello"
是可扩张的,因为可以对它执行这两种扩张操作使得 query = "hello" -> "hellooo" -> "helllllooo" = s
。
输入一组查询单词,输出其中可扩张的单词数量。
示例:
输入:
s = "heeellooo"
words = ["hello", "hi", "helo"]
输出:1
解释:
- 我们能通过扩张 “hello” 的 “e” 和 “o” 来得到 “heeellooo”。
- 我们不能通过扩张 “helo” 来得到 “heeellooo” 因为 “ll” 的长度小于 3 。
提示:
1 <= s.length, words.length <= 100
1 <= words[i].length <= 100
s 和所有在 words 中的单词都只由小写字母组成。
方法:字母组分解
将字符串分解为连续相同字符的字母组,比较每个字母组的字符和长度是否符合扩展条件。只有当所有对应的字母组满足字符相同且长度条件时,查询单词才是可扩张的。
- 分解字母组:将字符串转换为由字符及其连续出现次数组成的字母组列表。
- 比较字母组:
- 检查两个字符串的字母组数目是否相同。
- 逐个比较字母组的字符是否相同。
- 检查每个字母组的长度是否满足条件:原长度等于目标长度,或目标长度≥原长度且≥3。
代码实现(Java):
class Solution {public int expressiveWords(String s, String[] words) {List<Group> sGroups = getGroups(s);int count = 0;for (String word : words) {List<Group> wordGroups = getGroups(word);if (sGroups.size() != wordGroups.size()) continue;boolean valid = true;for (int i = 0; i < sGroups.size(); i++) {Group sGroup = sGroups.get(i);Group wordGroup = wordGroups.get(i);if (sGroup.c != wordGroup.c) {valid = false;break;}int sCount = sGroup.count;int wCount = wordGroup.count;if (sCount != wCount) {if (sCount < wCount || sCount < 3) {valid = false;break;}}}if (valid) {count++;}}return count;}private List<Group> getGroups(String s) {List<Group> groups = new ArrayList<>();if (s.isEmpty()) return groups;char prev = s.charAt(0);int count = 1;for (int i = 1; i < s.length(); i++) {char curr = s.charAt(i);if (curr == prev) {count++;} else {groups.add(new Group(prev, count));prev = curr;count = 1;}}groups.add(new Group(prev, count));return groups;}static class Group {char c;int count;Group(char c, int count) {this.c = c;this.count = count;}}
}
复杂度分析
- 时间复杂度:O(k * (m + n)),其中k是单词数量,m是s的长度,n是单词的平均长度。分解每个字符串的时间为O(m)或O(n)。
- 空间复杂度:O(m + n),存储字母组列表。
810. 黑板异或游戏
黑板上写着一个非负整数数组 nums[i]
。
Alice 和 Bob 轮流从黑板上擦掉一个数字,Alice 先手。如果擦除一个数字后,剩余的所有数字按位异或运算得出的结果等于 0
的话,当前玩家游戏失败。 另外,如果只剩一个数字,按位异或运算得到它本身;如果无数字剩余,按位异或运算结果为 0
。
并且,轮到某个玩家时,如果当前黑板上所有数字按位异或运算结果等于 0
,这个玩家获胜。
假设两个玩家每步都使用最优解,当且仅当 Alice 获胜时返回 true。
示例 1:
输入: nums = [1,1,2]
输出: false
解释:
1. Alice 有两个选择: 擦掉数字 1 或 2。
2. 如果擦掉 1, 数组变成 [1, 2]。剩余数字按位异或得到 1 XOR 2 = 3。那么 Bob 可以擦掉任意数字,因为 Alice 会成为擦掉最后一个数字的人,她总是会输。
3. 如果 Alice 擦掉 2,那么数组变成[1, 1]。剩余数字按位异或得到 1 XOR 1 = 0。Alice 仍然会输掉游戏。
示例 2:
输入: nums = [0,1]
输出: true
示例 3:
输入: nums = [1,2,3]
输出: true
提示:
1 <= nums.length <= 1000
0 <= nums[i] < 2^16
方法:数学条件判断
根据游戏规则推导,如果初始时所有数字的异或和为0,则Alice直接获胜。否则,当且仅当数组长度为偶数时,Alice可以通过最优策略获胜。
- 计算数组中所有元素的异或和。
- 若异或和为0,返回
true
。 - 否则,检查数组长度是否为偶数,返回对应的结果。
代码实现(Java):
class Solution {public boolean xorGame(int[] nums) {int xorSum = 0;for (int num : nums) {xorSum ^= num;}return xorSum == 0 || nums.length % 2 == 0;}
}
复杂度分析
- 时间复杂度:O(n),其中n是数组长度。遍历数组一次计算异或和。
- 空间复杂度:O(1),仅使用常数空间。
声明
- 本文版权归
CSDN
用户Allen Wurlitzer
所有,遵循CC-BY-SA
协议发布,转载请注明出处。- 本文题目来源
力扣-LeetCode
,著作权归领扣网络
所有。商业转载请联系官方授权,非商业转载请注明出处。
相关文章:
算法刷题记录——LeetCode篇(9.1) [第801~810题]
更新时间:2025-03-29 算法题解目录汇总:算法刷题记录——题解目录汇总技术博客总目录:计算机技术系列博客——目录页 优先整理热门100及面试150,不定期持续更新,欢迎关注! 801. 使序列递增的最小交换次数…...
AOA与TOA混合定位,MATLAB例程,自适应基站数量,三维空间下的运动轨迹,滤波使用EKF
本代码实现了一个基于 到达角(AOA) 和 到达时间(TOA) 的混合定位算法,结合 扩展卡尔曼滤波(EKF) 对三维运动目标的轨迹进行滤波优化。代码通过模拟动态目标与基站网络,展示了从信号测量、定位解算到轨迹滤波的全流程,适用于城市峡谷、室内等复杂环境下的定位研究。 文…...
【vllm/瞎折腾】在内网wsl上安装vllm并尝试多节点部署(失败了)
目录 说在前面miniconda安装外网创建虚拟环境创建节点一的虚拟环境创建节点二的虚拟环境 内网配置环境配置节点一的环境配置节点二的环境 vllm多节点配置节点一(主节点)配置节点二配置 部署LLM(失败)补充:wsl2设置ulimit补充:wsl安装libcuda补充…...
Mayo Clinic Platform在人工智能医疗领域的现状及启示意义研究
一、引言 1.1 研究背景与意义 在科技飞速发展的当下,人工智能(AI)已逐渐渗透至各个行业,医疗领域作为关乎人类生命健康的重要领域,也迎来了人工智能技术带来的深刻变革。人工智能医疗,作为人工智能与医疗行业深度融合的产物,正重塑着全球医疗的格局。 从全球范围来看,…...
k8s部署教程
Kubernetes 1. 使用Kubernetes部署Web服务器 我们的目标是部署三个实例,可以让用户直接访问。三个实例,这样即便一个崩溃了,也还有两个,比较不容易出问题。实际中你要根据自己的业务来判断。也就是说,我们需要一个…...
java基础:常见类和对象
1.常见类和对象: java.lang.Object类,Java中的每个类都直接或间接地继承自Object类,如果没有明确指定一个类继承另一个类,那么它的默认父类就是Object类; 例如多态: package java_jichu;public class ja…...
了解遗传算法的Matlab程序的奥妙之处
老板突然想要了解遗传算法的Matlab程序,我们需要先理清楚他们的需求。首先,老板可能对遗传算法有一定的了解,但不太清楚如何在Matlab中具体实现。他可能是一个学生或者研究人员,需要应用到某个项目中,比如优化问题。老板可能希望得到一个结构清晰的步骤说明,以及具体的代…...
Java学习------源码解析之StringBuilder
1. 介绍 String中还有两个常用的类,StringBuffer和StringBuilder。这两个类都是专门为频繁进行拼接字符串而准备的。最先出现的是StringBuffer,之后到jdk1.5的时候才有了StringBuilder。 2. StringBuilder解析 从这张继承结构图可以看出: S…...
【漫话机器学习系列】163.方差膨胀因子(Variance Inflation Factor, VIF)
方差膨胀因子(Variance Inflation Factor, VIF)详解 1. 什么是方差膨胀因子? 方差膨胀因子(Variance Inflation Factor, VIF)是一种用于衡量回归分析中多重共线性(Multicollinearity)程度的指…...
蓝桥杯省模拟赛 字符串拼接
问题描述 给定四个字符串 a,b,c,d,请将这四个字符串按照任意顺序依次连接拼成一个字符串。 请问拼成的字符串字典序最小是多少? 输入格式 输入四行,每行包含一个字符串。 输出格式 输出一行包含一个字符串,表示答案。 样例…...
前端路由守卫与后端权限验证,仅使用路由守卫是否安全?
前后端分离架构的安全原则 后端必须对所有 API 接口进行权限验证前端仅负责用户界面的重定向安全策略应始终由后端最终决定 问题1:前端设置路由守卫是否可以阻挡用户直接通过URL访问??? 前端路由守卫(如 Vue Router …...
React-nodejs 练习 个人博客
1.主要功能模块: 文章管理:CRUD操作 用户系统:注册、登录、权限控制评论系统:文章评论功能 2.技术栈: 前端:React Ant Design React Router后端:Express MongoDB 通信:RESTful…...
AI三大主义 和 深度学习三大主义
在人工智能(AI)研究领域,"三大主义"通常指三种核心方法论或思想流派,它们代表了不同的技术路径和哲学观点。以下是主流的划分方式: 1. 符号主义(Symbolicism) 核心思想:智…...
Linux实现生产者消费者模型(基于阻塞队列)
目录 概念及优势 代码实现 概念及优势 生产者消费者模型是一种用于线程同步的模型,在这个模型中有两种角色,生产者生产数据,消费者消费数据。有三种关系,生产者与生产者,消费者与消费者,生产者与消费者。…...
UE5 UE4 右键/最大化-菜单-不显示/闪/黑色/黑屏--修复方法
先关闭UE5 、UE4 编辑器。 进入这个网站:https://nvidia.custhelp.com/app/answers/detail/a_id/5157 网速慢,换成这个下载:https://download.csdn.net/download/qq_21153225/90546310 下载:mpo_disable.reg 的文件 只双击“mpo…...
[ C语言 ] | 从0到1?
目录 认识计算机语言 C语言 工欲善其事必先利其器 第一个C语言代码 这一些列 [ C语言 ] ,就来分享一下 C语言 相关的知识点~ 认识计算机语言 我们说到计算机语言,语言,就是用来沟通的工具,计算机语言呢?就是我们…...
4.训练篇2-毕设篇
resnet # 1. 从 torchvision 中加载预训练的 ResNet18 模型 # pretrainedTrue 表示使用在 ImageNet 上预训练过的参数,学习效果更好 base_model_resnet18 models.resnet18(pretrainedTrue)# 2. 获取 ResNet18 模型中全连接层(fc)的输入特征…...
Ubuntu 系统中,每日健康检查
一、手动检查命令(基础项) 1. 系统资源监控 内存使用: free -h # 查看内存和交换空间使用情况 cat /proc/meminfo | grep -i "memavailable" # 查看可用内存CPU 负载: top -n 1 -b | grep "load ave…...
#CX# UVM中的virtual sequence 和 virtual sequencer 的用途
在UVM中,Virtual Sequence(虚拟序列) 的核心用途是协调多个物理Sequencer上的Sequence执行,以实现跨接口、跨组件的复杂事务同步和场景控制。 1. 核心用途 多接口协同测试 当验证场景需要多个接口(如DUT的AXI、I2C、UART接口)同时或按特定顺序发送事务时,Virtual Seque…...
vue:突然发现onok无法使用
const that this;this.$confirm({title: "修改商品提示",content: "如果当前商品存在于商品活动库,则在商品活动库的状态会下架",onOk: function () {that.submitForm();}}); 突然发现 this.$confirm无法进入onok 最终发现是主题冲突&#x…...
开发过程中需要安装的浏览器插件
Vue.js devtools https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hlzh-CN&utm_sourceext_sidebar ModHeader https://chromewebstore.google.com/detail/modheader-modify-http-hea/idgpnmonknjnojddfkpgkljpfnnfcklj?utm…...
基于javaweb的SpringBoot房屋出租系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...
小程序某点餐平台全自动化实现思路
某德基全自动化实现 一、实现思路二、具体步骤1、分析接口2、破解接口3、解决自动支付4、获取订单 三、其他 以下内容仅供学习交流使用 粗略讲解一下思路,要完全实现只靠以下这些内容还是不够的。 一、实现思路 全自动化实现用的是小程序版本。我们首先要分析整个…...
红宝书第二十讲:详解JavaScript的Proxy与Reflect
红宝书第二十讲:详解JavaScript的Proxy与Reflect 资料取自《JavaScript高级程序设计(第5版)》。 查看总目录:红宝书学习大纲 一、Proxy的作用:给对象戴上“监听耳机” Proxy(代理)允许你为对象…...
Contactile三轴触觉传感器:多维力感赋能机器人抓取
在非结构化环境中,机器人对物体的精准抓取与操作始终面临巨大挑战。传统传感器因无法全面感知触觉参数(如三维力、位移、摩擦),难以适应复杂多变的场景。Contactile推出的三轴触觉力传感器,通过仿生设计与创新光学技术…...
18-动规-子序列中的 k 种字母(中等)
题目 来源 28. 子序列中的 k 种字母(第一期模拟笔试) 思路 基本分析 子序列的定义 子序列是从原序列中选取部分元素,同时保持这些元素在原序列中的相对顺序所形成的新序列。也就是说,子序列中的元素不需要在原序列中连续出现…...
Lua 数组
Lua 数组 引言 Lua 是一种轻量级、高效的脚本语言,广泛应用于游戏开发、服务器端编程等领域。在 Lua 中,数组是一种非常重要的数据结构,它允许开发者以高效的方式存储和操作一系列数据。本文将详细介绍 Lua 数组的相关知识,包括…...
C 语言的未来:在变革中坚守核心价值
一、从 “古老” 到 “长青”:C 语言的不可替代性 诞生于 20 世纪 70 年代的 C 语言,历经半个世纪的技术浪潮,至今仍是编程世界的 “基石语言”。尽管 Python、Java 等高级语言在应用层开发中占据主流,但 C 语言在系统级编程和资…...
springboot3 基于 logback
1.配置 logging:level:root: ${ROOT_LOG_LEVEL:debug}web: ${ROOT_WEB_LEVEL:info}org.hibernate.orm.jdbc.bind: ${ROOT_SQL_PARAM_LEVEL:info} #打印SQL参数2.基于 logback-spring.xml配置 <?xml version="1.0" encoding="UTF-8"?> <configu…...
网络相关的知识总结1
1.设备可以通过以太网电缆(如双绞线)连接到交换机的端口,交换机也通过以太网电缆连接到路由器。但是如果距离过远,比如跨国路由器如何连接? 1.专用通信线路(如 MPLS、光纤专线):租用…...
Rust vs. Go: 性能测试(2025)
本内容是对知名性能评测博主 Anton Putra Rust vs. Go (Golang): Performance 2025 内容的翻译与整理, 有适当删减, 相关数据和结论以原作结论为准。 再次对比 Rust 和 Go,但这次我们使用的是最具性能优势的 HTTP 服务器库---Hyper,它基于 Tokio 异步运…...
如何使用postman调用多参数接口(包含文件上传)
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 如何使用postman调用包含文件参数的多参数接…...
无人机助力道路智能养护,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建无人机航拍道路交通场景下水泥路面缺陷智能检测识别系统
道路养护是保障交通命脉安全的隐形防线,其重要性不亚于道路建设本身。我国每年因道路病害引发的交通事故占比高达12%,及时修复1平方米的早期裂缝可避免后续数万元的修复成本。在这场与道路病害赛跑的战役中,传统养护模式正遭遇前所未有的挑战…...
28_跨域
目录 promise promise的基本语法 async await try catch promise 静态方法 跨域 跨域的解决方案 1-cors 编辑 2-jsonp方案 3-代理服务器 promise promise 是一个es6新增的语法 承诺的意思 作用:是专门用来解决回调地狱!!!! promise的基本语法 // 基本语法:// Pr…...
【C#.NET】VS2022创建Web API项目
C# Web API 是一种基于 .NET 平台(包括但不限于.NET Framework 和 .NET Core)构建 HTTP 服务的框架,用于创建 RESTful Web 服务。REST(Representational State Transfer)是一种软件架构风格,它利用HTTP协议…...
注意力蒸馏技术
文章目录 摘要abstract论文摘要简介方法预备知识注意力蒸馏损失注意力引导采样 实验结论总结参考文献 摘要 本周阅读了一篇25年二月份发表于CVPR 的论文《Attention Distillation: A Unified Approach to Visual Characteristics Transfer》,论文开发了Attention Distillation…...
Day17 -实例:利用不同语言不同框架的特征 进行识别
前置:我们所需的web站点,都可以利用fofa去搜索,例如:app"flask"这样的语句去找对应的站点,找到后,我们模拟不知道是什么框架,再根据特征去判断它的框架。 ***利用工具可以再去结合大…...
Centos7 安装 TDengine
Centos7 安装 TDengine 1、简介 官网: https://www.taosdata.com TDengine 是一款开源、高性能、云原生的时序数据库(Time Series Database, TSDB), 它专为物联网、车联网、工业互联网、金融、IT 运维等场景优化设计。同时它还带有内建的缓…...
DeepSeek调用API访问,使用AnythingLLM建立本地知识库后开放API调用,ApiFox/PostMan调用本地DeepSeek
上篇文章中我们使用AnythingLLM成功在本地部署了DeepSeek的本地知识库,并且上传了几个文件让DeepSeek学习,可点击查看: 本地部署DeepSeek并使用AnythingLLM建立本地知识库全流程,DeepSeek-R1:7b本地安装部署,DeepSeek-R1本地部署…...
SQL语句---DDL
文章目录 1、SQL语句2、DDL2.1 数据库的操作显示当前的数据库创建数据库指定编码删除数据库切换当前数据库 2.2 数据表的操作显示表创建表显示表结构修改表添加新的字段删除原有字段 修改原有字段删除数据表 2.3 Mysql数据库中常用的数据类型 1、SQL语句 结构化查询语句&#…...
Java实战:实现用户的登录注册功能
系列文章目录 Java文件 I/O流的操作实战和高级UI组件和事件监听的综合 文章目录 系列文章目录前言一、大致流程思路分析:二、定义用户类:三、服务层的实现: 1.保护用户数据功能的实现2.登录操作的实现 四、实现用户的注册界面: 大…...
用LLama factory时报类似Process 2504721 got signal: 1的解决方法
之前用nohup来远程跑LLama factory微调脚本,是没有问题的,但今天发现运行类似下面这个命令时, nohup llamafactory-cli train examples/train_qlora/qwen_lora.yaml 只要一关闭ssh session,就会终止训练,报类似&…...
WPF ContentTemplate
ContentTemplate 是一个非常重要的属性,用于定义 ContentPresenter 中内容的显示样式。通过设置 ContentTemplate,你可以控制 ContentPresenter 如何呈现其绑定的内容。 下面是对 ContentTemplate 的详细解释以及它的作用和用法。 1. ContentTemplate 的…...
powershell7.5.0不支持conda的问题
经历:这周手欠使用vscode的powershell时提示我更新,我就更新了,更新完激活不了conda环境了,查询了半天是powershell最新版7.5.0与目前conda25.1.1以前的版本不支持的问题。 问题环境:powershell版本>7.5.0ÿ…...
SSE SseEmitter.completeWithError(e) 触发的处理逻辑
在 Java 客户端使用 OkHttp 监听 SSE(Server-Sent Events) 的情况下,当服务端调用 SseEmitter.completeWithError(e),客户端会触发 EventSourceListener 的 onFailure() 方法(而不是 onError)。 1. 服务端&…...
JAVA反序列化深入学习(八):CommonsCollections6
与CC5相似: 在 CC5 中使用了 TiedMapEntry#toString 来触发 LazyMap#get在 CC6 中是通过 TiedMapEntry#hashCode 来触发 LazyMap#get 之前看到了 hashcode 方法也会调用 getValue() 方法然后调用到其中 map 的 get 方法触发 LazyMap,那重点就在于如何在反…...
科技快讯 | 韩国科学家研发出全球首款仿生液态机器人;OpenAI推出GPT-4o图像生成功能
韩国科学家研发出全球首款仿生液态机器人,自由变形穿越金属栅栏 韩国首尔大学等研究团队开发出一种基于液体的下一代软体机器人,具有细胞仿生特性,能自由变形、分裂融合,并执行物质运输任务。该机器人采用“颗粒装甲”设计&#x…...
[Vue2]v-model用于表单
之前我们讲到过v-model用于双向绑定一个数据,通常用于表单提交数据。而之前的演示里只演示了文本输入栏,这里详细演示一下其他表单输入时使用v-model。 文本输入 文本输入数据就是经典的type"text": <input type"text&qu…...
【机器学习】imagenet2012 数据预处理数据预处理
【机器学习】数据预处理 1. 下载/解压数据2. 数据预处理3. 加载以及训练代码3.1 使用PIL等加载代码3.2 使用OpenCV的方式来一张张加载代码3.3 h5的方式来加载大文件 最后总结 这个数据大约 140个G,128w的训练集 1. 下载/解压数据 首先需要下载数据: 数据最后处理…...
基于pycatia的CATIA零部件激活状态管理技术解析
一、问题背景:CATIA激活状态管理的痛点 在CATIA V5/V6的装配设计过程中,工程师经常使用激活状态控制(Activation)来管理大型装配体的显示性能。但实际使用中存在一个典型问题:当零部件被取消激活(Deac…...