Leetcode 第 394 场周赛

news2024/10/1 7:42:27

Leetcode 第 394 场周赛

    • 1. [统计特殊字母的数量 I](https://leetcode.cn/problems/count-the-number-of-special-characters-i/)
    • 2. [统计特殊字母的数量 II](https://leetcode.cn/problems/count-the-number-of-special-characters-ii/)
    • 3. [使矩阵满足条件的最少操作次数](https://leetcode.cn/problems/minimum-number-of-operations-to-satisfy-conditions/)
    • 4. [最短路径中的边](https://leetcode.cn/problems/find-edges-in-shortest-paths/)

本次周赛是手速场,奈何我卡在第三题实在是太久了,其实第四题比第三题要简单,第四题图论题就是非常简单的单次迪杰斯特拉+父节点回溯,第三题是动态规划反而不太好想出来,一开始写了半天的 DFS 遍历结果只能过 50% 的用例……

  1. 统计特殊字母的数量 I
  2. 统计特殊字母的数量 II
  3. 使矩阵满足条件的最少操作次数
  4. 最短路径中的边

1. 统计特殊字母的数量 I

给你一个字符串 word。如果 word 中同时存在某个字母的小写形式和大写形式,则称这个字母为 特殊字母

返回 word特殊字母 的数量。

示例 1:

输入: word = “aaAbcBC”
输出: 3
解释:
word 中的特殊字母是 'a''b''c'

示例 2:

输入: word = “abc”
输出: 0
解释:
word 中不存在大小写形式同时出现的字母。

示例 3:

输入: word = “abBCab”
输出: 1
解释:
word 中唯一的特殊字母是 'b'

提示:

  • 1 <= word.length <= 50
  • word 仅由小写和大写英文字母组成。

模拟题,没啥好说的,看完题之后再仔细读几遍题,确保没有坑之后就可以开始动手实现了,比较简单。

class Solution {
public:
    int numberOfSpecialChars(string word) {
        vector<int> lowerMark(26);
        vector<int> upperMark(26);
        for (const char& c : word) {
            if ((int)c >= 97)
                lowerMark[(int)c - 97] = 1;
            else
                upperMark[(int)c - 65] = 1;
        }
        int ans = 0;
        for (int i = 0; i < 26; ++i)
            ans += lowerMark[i] & upperMark[i];
        return ans;
    }
};

2. 统计特殊字母的数量 II

给你一个字符串 word。如果 word 中同时出现某个字母 c 的小写形式和大写形式,并且 每个 小写形式的 c 都出现在第一个大写形式的 c 之前,则称字母 c 是一个 特殊字母

返回 word特殊字母 的数量。

示例 1:

输入: word = “aaAbcBC”
输出: 3
解释:
特殊字母是 'a''b''c'

示例 2:

输入: word = “abc”
输出: 0
解释:
word 中不存在特殊字母。

示例 3:

输入: word = “AbBCab”
输出: 0
解释:
word 中不存在特殊字母。

提示:

  • 1 <= word.length <= 2 * 105
  • word 仅由小写和大写英文字母组成。

非常好模拟题,使我的数组旋转。还是简单的模拟题,开两个数组,分别记录小写字母最后一次出现的位置以及大写字母第一次出现的位置,最后统计两个数组对应位置上符合题目的 “小写字母最后一次位置小于大写字母第一次位置” 的数量即可(由于我初始化为 -1 ,因此还需额外判断是否存在,而不只是简单的小于关系,否则 − 1 < 0 -1<0 1<0 这种也被判定为合法就是错的,因为 − 1 -1 1 代表这个字符没有出现在字符串中)。

class Solution {
public:
    int numberOfSpecialChars(string word) {
        vector<int> lowerMark(26, -1);
        vector<int> upperMark(26, -1);
        int len = word.length();
        for (int i = 0; i < len; ++i) {
            if ((int)word[i] >= 97)
                lowerMark[(int)word[i] - 97] = i;
            else if (upperMark[(int)word[i] - 65] < 0)
                upperMark[(int)word[i] - 65] = i;
        }
        int ans = 0;
        for (int i = 0; i < 26; ++i)
            ans += (int)(lowerMark[i] >= 0 && upperMark[i] >= 0 && lowerMark[i] < upperMark[i]);
        return ans;
    }
};

3. 使矩阵满足条件的最少操作次数

给你一个大小为 m x n 的二维矩形 grid 。每次 操作 中,你可以将 任一 格子的值修改为 任意 非负整数。完成所有操作后,你需要确保每个格子 grid[i][j] 的值满足:

  • 如果下面相邻格子存在的话,它们的值相等,也就是 grid[i][j] == grid[i + 1][j](如果存在)。
  • 如果右边相邻格子存在的话,它们的值不相等,也就是 grid[i][j] != grid[i][j + 1](如果存在)。

请你返回需要的 最少 操作数目。

示例 1:

输入: grid = [[1,0,2],[1,0,2]]
输出: 0
解释:
在这里插入图片描述

矩阵中所有格子已经满足要求。

示例 2:

输入: grid = [[1,1,1],[0,0,0]]
输出: 3
解释:

将矩阵变成 [[1,0,1],[1,0,1]] ,它满足所有要求,需要 3 次操作:

  • grid[1][0] 变为 1 。
  • grid[0][1] 变为 0 。
  • grid[1][2] 变为 1 。

示例 3:

输入: grid = [[1],[2],[3]]
输出: 2
解释:

这个矩阵只有一列,我们可以通过 2 次操作将所有格子里的值变为 1 。

提示:

  • 1 <= n, m <= 1000
  • 0 <= grid[i][j] <= 9

根据题目的描述,我们可以把题目转换为更清晰明了的约束:

  • 每一列值必须相同
  • 相邻两列值必须不同
    那么不受约束的列应该是最右边那一列,它的选择将作为初始约束一直链式约束到第一列,至于每一列调整成哪个数,那当然是看每一列哪个数出现的次数最多,那么剩下需要调整为众数的位置就越少,需要花费的调整次数就越少。不过这是一种贪心的想法,本题能用贪心吗?简单思考一下,如果第一列选择了它那列最优的数字导致第二列不能选某个数字进而导致第三列不能选到最优选择,进而导致非常多后续的列都无法选择到最优数,这是得不偿失的,因此我们没有办法证明这种贪心思路是正确的,只能每列都尝试一遍哪个数会导致总体最优的结果。由于最右边的列是不受约束的,因此 DFS 自然是从最右边的列开始了。

统计各列出现的数的次数,然后 DFS 回溯的时候 记录/消除 本列已选择数的状态,把每一列的每个数都尝试一遍,累积每一列的修改次数,完成最后一列修改之后和最小值比较维护更新。

class Solution {
private:
    int m; // row
    int n; // col
    vector<unordered_map<int, int>> colNumCnt;
    vector<int> colChoice; // choice of each column
    int ans;
    
    
private:
    void dfs(int colIdx, const int& tmp) {
        // will dfs 1000 level at most (equal to the number of column)
        if (colIdx < 0) {
            ans = min(ans, tmp);
            return;
        }
        if (tmp >= ans)
            return; // no need to dfs more
        
        for (auto [k, v] : colNumCnt[colIdx]) {
            colChoice[colIdx] = k;
            
            if (colIdx < n - 1 && colChoice[colIdx] == colChoice[colIdx + 1])
                continue;
            else
                dfs(colIdx - 1, tmp + m - v);
            
            colChoice[colIdx] = -1;
        }
    }
    
public:
    int minimumOperations(vector<vector<int>>& grid) {
        // some initializations
        m = grid.size();
        n = grid[0].size();
        colNumCnt = vector<unordered_map<int, int>>(n);
        colChoice = vector<int>(n, -1);
        ans = INT_MAX;
        
        // ensurance, incase that each col just have 1 kind of digit
        for (int j = 0; j < n; ++j)
            for (int k = 0; k < 10; ++k)
                colNumCnt[j][k] = 0;
        // record times of each digit in each column
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                colNumCnt[j][grid[i][j]]++;
            }
        }
        
        // dfs
        dfs(n - 1, 0);
        return ans;
    }
};

发现会超时,所以这题没有继续做下去了,当时就感觉是 DP 了,因为能 完全遍历DFS 的情况很多时候都能用 DP 替代。竞赛结束之后看了看交流区的题解,确实是 动态规划 ,并且也不是很难的动态规划。因为调整结束后,每一列的值一定相同,所以动态规划的单词操作就是把一整列赋值为某个值使得子问题的解最优。定义 d p [ i ] [ j ] dp[i][j] dp[i][j] 为计算到第 i i i 列时,前一列选择数为 j j j 的时候具有的最小值, j ∈ [ 0 ,   9 ] j \in [0,\ 9] j[0, 9] ,因此 d p [ i ] [ j ] dp[i][j] dp[i][j] 所依赖的子问题就是 d p [ i − 1 ] [ 0 ] ,   … ,   d p [ i − 1 ] [ 9 ] dp[i-1][0],\ \dots,\ dp[i-1][9] dp[i1][0], , dp[i1][9] 了,因此当前问题依赖的子问题全部属于相邻的上一列,则二维的动态规划矩阵可以使用滚动数组来实现空间复杂度的优化。枚举当前列选择各个数字 [ 0 ,   9 ] [0,\ 9] [0, 9] ,通过依赖上一列子问题来求解出每个枚举的最优解,当前调整次数即:上一列调整次数+当前列枚举的数所需剩余调整次数。

class Solution {
public:
    int minimumOperations(vector<vector<int>>& grid) {
        int m = grid.size();    // m rows
        int n = grid[0].size(); // n cols

        vector<int> dpcurr(10); // must pre-initialized
        vector<int> dpprev(10); // must pre-initialized
        vector<int> colcnt(10); // must pre-initialized
        for (int col = n-1; col >= 0; --col) {
            dpcurr = vector<int>(10, 1<<31-1);
            colcnt = vector<int>(10, 0);
            for (int row = 0; row < m; ++row)
                colcnt[grid[row][col]]++;
            for (int i = 0; i < 10; ++i) {
                for (int j = 0; j < 10; ++j) {
                    if (i ^ j) {
                        dpcurr[i] = min(dpcurr[i], dpprev[j] + m - colcnt[i]);
                    }
                }
            }
            dpprev = dpcurr;
        }
        return *std::min_element(dpprev.begin(), dpprev.end());
    }
};

4. 最短路径中的边

给你一个 n 个节点的无向带权图,节点编号为 0n - 1 。图中总共有 m 条边,用二维数组 edges 表示,其中 edges[i] = [ai, bi, wi] 表示节点 aibi 之间有一条边权为 wi 的边。

对于节点 0 为出发点,节点 n - 1 为结束点的所有最短路,你需要返回一个长度为 mboolean 数组 answer ,如果 edges[i] 至少 在其中一条最短路上,那么 answer[i]true ,否则 answer[i]false

请你返回数组 answer

注意,图可能不连通。

示例 1:
在这里插入图片描述

输入: n = 6, edges = [[0,1,4],[0,2,1],[1,3,2],[1,4,3],[1,5,1],[2,3,1],[3,5,3],[4,5,2]]
输出: [true,true,true,false,true,true,true,false]
解释:
以下为节点 0 出发到达节点 5 的 所有 最短路:

  • 路径 0 -> 1 -> 5 :边权和为 4 + 1 = 5
  • 路径 0 -> 2 -> 3 -> 5 :边权和为 1 + 1 + 3 = 5
  • 路径 0 -> 2 -> 3 -> 1 -> 5 :边权和为 1 + 1 + 2 + 1 = 5

示例 2:

输入: n = 4, edges = [[2,0,1],[0,1,1],[0,3,4],[3,2,2]]
输出: [true,false,false,true]
解释:
只有一条从节点 0 出发到达节点 3 的最短路 0 -> 2 -> 3 ,边权和为 1 + 2 = 3

提示:

  • 2 <= n <= 5 * 10^4
  • m == edges.length
  • 1 <= m <= min(5 * 10^4, n * (n - 1) / 2)
  • 0 <= ai, bi < n
  • ai != bi
  • 1 <= wi <= 10^5
  • 图中没有重边。

早知道第四题这么简单就不去死磕第三题了,第三题卡了我半天 DFS 结果还只能过一半的用例。第四题没什么特殊技巧,就是使用迪杰斯特拉记录单源最短路径(多条)然后记录每个节点的来向父节点,最后从终点回溯到起点顺便把经过的边记录到哈希表中以供查询即可。

需要注意的是迪杰斯特拉的设计方式,因为普通的迪杰斯特拉模板只是计算单源最短路径(单个节点到其他节点)的权值之和,但是并不会记录路径,所以必须额外开一个父节点数组,记录每个节点在 迪杰斯特拉BFS 过程中最短路径上的父节点是谁,这样方便后续能从终点回溯到起点。当记录每个节点的路径父节点时需注意,如果多条路径在不同时刻到达同一个节点,且到达时所花费的路径权值之和相同,则无需再将该节点重复入队,否则试想当一个节点被成千上万个节点相连时,每条达到该节点处的路径都将重复的将该节点入队,这是没必要的,因为第一条来到该节点的路径已经负责把该节点入队了,其他到达该节点的路径只需要负责记录路径父节点关系,无需重复将该节点入队,否则当图的边是比较稠密的时候,时间复杂度会大大增加。因此我们在将一个节点入队的时候需要判断到达此节点的路径目前权值之和:

  • 更小,我们找到了一条更短的路径,这条路径的父节点关系应该覆盖掉之前已经存在的父节点关系
  • 相等,我们找到了一条额外的路径,这条路径的父节点关系应该添加到之前已经存在的父节点关系
  • 更大,什么也不做
class Solution {
public:
    vector<bool> findAnswer(int n, vector<vector<int>>& edges) {
        unordered_map<int, unordered_map<int, int>> graph;
        for (const vector<int>& edge : edges) {
            graph[edge[0]][edge[1]] = edge[2];
            graph[edge[1]][edge[0]] = edge[2];
        }

        // perform dijkstra once to find all shortest path
        vector<vector<int>> parent(n);
        vector<int> dist(n, INT_MAX);
        queue<pair<int, int>> dijkstraQ;
        dist[0] = 0;
        dijkstraQ.emplace(0, dist[0]);
        while (!dijkstraQ.empty()) {
            auto [curr, cdst] = dijkstraQ.front();
            dijkstraQ.pop();
            for (auto [next, ewgh] : graph[curr]) {
                int ndst = cdst + ewgh;
                if (ndst <= dist[next]) {
                    if (ndst < dist[next]) {
                        dist[next] = ndst;
                        parent[next].clear();
                        dijkstraQ.emplace(next, ndst);
                    }
                    parent[next].emplace_back(curr);
                }
            }
        }
        // restore path from parent relationship
        unordered_map<int, unordered_map<int, bool>> valid;
        vector<bool> rvSeen(n, false);
        queue<int> backtrackQ;
        backtrackQ.emplace(n-1);
        rvSeen[n-1] = true;
        while (!backtrackQ.empty()) {
            int curr = backtrackQ.front();
            backtrackQ.pop();
            for (const int& next : parent[curr]) {
                valid[curr][next] = true;
                valid[next][curr] = true;
                if (rvSeen[next]) continue;
                rvSeen[next] = true;
                backtrackQ.emplace(next);
            }
        }

        vector<bool> ans(edges.size(), false);
        for (int i = 0; i < edges.size(); ++i) {
            const vector<int>& edge = edges[i];
            if (valid[edge[0]][edge[1]] || valid[edge[1]][edge[0]])
                ans[i] = true;
        }

        return ans;
    }
};

注意通过从终点回溯到起点来从父节点关系恢复边关系的时候,也是一样存在前文提到的多条可能路径访问到同一个节点是否要重复入队的问题,因为一条边我们只需要经过一次即可恢复,那么多条可能的路径回溯的时候在不同时刻回到同一节点,当然是只需要第一时刻回溯到该节点的路径负责入队该节点来扩散之后的回溯(也就是使得后续的 BFS 只生效一次),其他后续时刻到来的路径探测只需要恢复与该节点的边关系即可了(如果还入队该节点那么后续的 BFS 会重复执行多次,没必要)。

另外对于只有正边权值的图,进行迪杰斯特拉 BFS 的时候,无需额外的维护一个 “已访问” 节点变量,可以通过到达节点的路径的权值之和判断一个节点是否是回头路,如果绕回头路到达一个节点那么权值之和肯定大于节点已经记录在案的最短距离,因此:

  • 新路径权值之和小于节点记录的距离:入队,此时 迪杰斯特拉BFS 对每个节点只计算一条最短路径,尽管可能存在多条同样距离的最短路径
  • 新路径权值之和小于等于节点记录的距离:入队,此时 迪杰斯特拉BFS 对每个节点计算多条最短路径,如果存在多条同样距离的最短路径

最后的边是否存在于最短路径上的判断,我一开始还很天真的想用 unordered_map<pair<int, int>, bool> 发现不行,这个 pair<int, int> 默认没有重载哈希。但是 pair<int, int> 是标准库实现了比较运算的,因此可以使用基于红黑树的 set<pair<int, int>> 来做查询。我试了一下,用哈希表的空间占用是 290MB ,用红黑树的空间占用是 216MB。

// restore path from parent relationship
set<pair<int, int>> valid;
vector<bool> rvSeen(n, false);
queue<int> backtrackQ;
backtrackQ.emplace(n-1);
rvSeen[n-1] = true;
while (!backtrackQ.empty()) {
	int curr = backtrackQ.front();
	backtrackQ.pop();
	for (const int& next : parent[curr]) {
		valid.emplace(curr, next);
		valid.emplace(next, curr);
		if (rvSeen[next]) continue;
		rvSeen[next] = true;
		backtrackQ.emplace(next);
	}
}

vector<bool> ans(edges.size(), false);
for (int i = 0; i < edges.size(); ++i) {
	const vector<int>& edge = edges[i];
	if (valid.count(pair<int, int>(edge[0], edge[1])) || valid.count(pair<int, int>(edge[1], edge[0])))
		ans[i] = true;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1614015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大一考核题解

在本篇中&#xff0c;将尽力使用多种解法&#xff0c;来达到一题多练的效果。 1&#xff1a; 1.原题链接&#xff1a; 238. 除自身以外数组的乘积 - 力扣&#xff08;LeetCode&#xff09; 这道题首先一眼肯定想到拿整体的积除以当前元素&#xff0c;将结果作为ans&#xff0c;…

护眼台灯哪个牌子最好?盘点五款目前比较好用的护眼台灯

护眼台灯哪个牌子好&#xff1f;护眼台灯比较好的牌子有书客、雷士、爱德华医生等。这些护眼台灯得益于强大的研发实力&#xff0c;不仅具备基础的照明功能&#xff0c;更在护眼效果上表现卓越。它们能够真正起到保护眼睛的作用&#xff0c;有效缓解眼部疲劳&#xff0c;为阅读…

Unity3D 羊了个羊等游戏工程源码/3D资源 大合集

Unity3D休闲益智游戏工程源码大合集 一、关卡类游戏工程源码二、跑酷类游戏工程源码三、消除合成类游戏工程源码四、棋牌类游戏工程源码五、RPG(角色扮演)类游戏工程源码六、FPS&#xff08;射击&#xff09;类游戏工程源码十、Unity3D工艺仿真六、Unity游戏资源1、Unity3D 吃鸡…

怎样快速打造二级分销小程序

乔拓云是一个专门开发小程序模板的平台&#xff0c;致力于帮助商家快速上线自己的小程序。通过套用乔拓云提供的精美模板&#xff0c;商家无需具备专业的技术背景&#xff0c;也能轻松打造出功能齐全、美观大方的小程序。 在乔拓云的官网&#xff0c;商家可以免费注册账号并登录…

【批量区域识别内容重命名】批量识别图片区域文字并重命名,批量图片部分识别内容重命文件,PDF区域识别提取重命名

我们在工作和生活中经常遇到这样的需求&#xff1a;比如将以下的图片区域识别进行重命名&#xff0c;批量识别后改成以时间和工作内容重命名&#xff0c;便于日后检索&#xff0c;快速查询 首先我们拍摄照片用到的是水印相机&#xff0c;这里的文字呢我们需要加个背景&#xff…

[数字人]唇形驱动,不生成头部动作算法总结

安全验证 - 知乎知乎&#xff0c;中文互联网高质量的问答社区和创作者聚集的原创内容平台&#xff0c;于 2011 年 1 月正式上线&#xff0c;以「让人们更好的分享知识、经验和见解&#xff0c;找到自己的解答」为品牌使命。知乎凭借认真、专业、友善的社区氛围、独特的产品机制…

【数据结构】时间复杂度的例题

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;数据结构 &#x1f337;追光的人&#xff0c;终会万丈光芒 前言&#xff1a; 这篇文章是关于时间复杂度的一些例题&#xff0c;关于时间复杂度和空间复杂度和算法的计算效率的基本知识点我放在…

【题解】NC1 大数加法(高精度加法)

https://editor.csdn.net/md?not_checkout1&spm1015.2103.3001.8066&articleId138048516 class Solution { public:string solve(string s, string t) {// write code herestring ret;int tmp 0; // 进位 本次累加和int i s.size()-1, j t.size()-1;while (i &g…

Token 在 LLM

大语言模型不能理解原始文本,所以需要把原始文本转换成大语言模型可以理解的数字表示形式,经过大模型处理以后,需要将该数字表示形式转换为人可以理解的文本。 原始文本到 token 原始文本转换为token序列的过程通常是在LLM的预处理阶段完成的。 在大型语言模型(LLM)中,tok…

五一营销新趋势:出海品牌如何利用TikTok掀起热潮

数字化时代&#xff0c;TikTok作为当下全球热门的短视频社交平台&#xff0c;以其独特的内容生态和庞大的用户基础&#xff0c;成为出海品牌进行营销的重要阵地。2024年五一国际劳动节即将来临&#xff0c;如何利用TikTok平台进行有效的营销活动&#xff0c;是每个出海品牌都需…

【埋点探针】微信小程序SDK安装

一、下载微信小程序SDK埋点代码 选择Wechat&#xff0c;复制sdk代码 在项目根目录下&#xff0c;创建sdk文件&#xff0c;webfunny.event.js 二、在app.js文件中&#xff0c;引入埋点SDK代码 首先引入sdk代码 require("./webfunny.event.js")引入兼容代码&#x…

TCP传输的粘包问题和各种异常情况

文章目录 粘包问题用分隔符用数字代表长度 TCP传输可能遇到的异常情况进程终止电脑关机正常情况下关机非正常情况关机&#xff08;停电&#xff09;电脑断网 粘包问题 粘包问题其实并不是TCP独有的的问题而是每一个面向字节流都会出现的问题&#xff0c;那么什么是粘包问题呢&…

最近做的一些套利操作

最近做的套利不多&#xff0c;主要是两个品种&#xff1a;全球芯片LOF&#xff0c;标普500LOF&#xff0c;一共盈利1360元。 盈利不多&#xff0c;但是每天我只花了3分钟点几下就赚到了&#xff0c;捡钱就像呼吸一样简单&#xff0c;还要啥自行车&#xff1f; 整理交易记录的…

如何增强Java GCExcel API 的导入和导出性能

前言 GrapeCity Documents for Excel (以下简称GcExcel) 是葡萄城公司的一款服务端表格组件&#xff0c;它提供了一组全面的 API 以编程方式生成 Excel (XLSX) 电子表格文档的功能&#xff0c;支持为多个平台创建、操作、转换和共享与 Microsoft Excel 兼容的电子表格&#xf…

JavaScript —— APIs(三)

一、事件流 &#xff08;一&#xff09;定义 &#xff08;二&#xff09;事件捕获 事件捕获&#xff0c;对话框从大到小弹出&#xff0c;先弹出爷爷&#xff0c;最后弹出儿子 &#xff08;三&#xff09;事件冒泡 冒泡事件&#xff0c;对话框从小到大弹出&#xff0c;先弹出…

【C++】C++11 包装器

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 function包装器 fu…

大模型接口管理和分发系统One API

老苏就职于一家专注于音视频实时交互技术和智能算法的创新企业。公司通过提供全面的 SDK 和解决方案&#xff0c;助力用户轻松实现实时音视频通话和消息传递等功能。尽管公司网站上有详细的文档中心&#xff0c;但在实际开发中&#xff0c;仍面临大量咨询工作。 鉴于此&#x…

单页面首屏优化,打包后大小减少64M,加载速度快了13.6秒

需求背景 从第三方采购的vue2 ElementUI实现的云管平台&#xff0c;乙方说2011年左右就开始有这个项目了&#xff08;那时候有Vue了吗&#xff0c;思考.jpg&#xff09;。十几年的项目&#xff0c;我何德何能可以担此责任。里面的代码经过多人多年迭代可以用惨不忍睹来形容&a…

大模型培训老师叶梓:通过微调提升小型语言模型的复杂推理能力

在人工智能的快速发展中&#xff0c;复杂推理能力的提升一直是研究者们追求的目标。最近&#xff0c;一项发表在arXiv上的研究成果【1】&#xff0c;提出了一种创新的方法&#xff0c;即通过微调小型语言模型&#xff08;LMs&#xff09;&#xff0c;并将其与大型语言模型&…

内旋风铣也挺有意思,不够还没搞透

内旋风铣&#xff0c;这一术语在机械制造业中并不陌生&#xff0c;它代表着一种高效且精确的加工方法。这一技术的名称“内旋风铣”便揭示了其两大核心特点&#xff1a;一是“内”&#xff0c;指的是在工件内部进行加工&#xff0c;通常涉及到难以触及的复杂曲面&#xff1b;二…