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

LeetCode234~258题解

LeetCode235.二叉搜索树的最近公共祖先:

题目描述:

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]

微信截图_20250110193701.png

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。

示例 2:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉搜索树中。

思路:

题意:找到两个节点的最近公共祖先

对于树的遍历问题,就是要考虑当前节点和左右儿子的关系,从相邻两层的关系去找答案的规律,从而形成整个树的递归

微信截图_20250110194009.png

时间复杂度:O(h),h为树的高度

注释代码:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(p -> val > q -> val) swap(p, q);if(p -> val <= root -> val && q -> val >= root -> val) return root;if(q -> val < root -> val) return lowestCommonAncestor(root -> left, p, q);else  return lowestCommonAncestor(root -> right, p , q);}
};

纯享版:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(!root) return NULL;if(p -> val > q -> val) swap(p, q);if(p -> val <= root -> val && q -> val >= root -> val) return root;if(q -> val < root -> val) return lowestCommonAncestor(root -> left, p, q);else return lowestCommonAncestor(root -> right, p, q);}
};

LeetCode236.二叉树的最近公共祖先:

题目描述:

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

示例 1:

微信截图_20250110202225.png

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。

示例 2:

微信截图_20250110202229.png

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。

示例 3:

输入:root = [1,2], p = 1, q = 2
输出:1

提示:

树中节点数目在范围 [2, 10^5] 内。
-10^9 <= Node.val <= 10^9
所有 Node.val 互不相同 。
p != q
p 和 q 均存在于给定的二叉树中。

y总方法:

时间复杂度:O(n)

代码:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:TreeNode* res;TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {dfs(root, p, q);return res;}int dfs(TreeNode*root, TreeNode* p, TreeNode* q){if(!root) return 0; //00:p和q都不存在 int state = dfs(root -> left, p, q);  //先将当前节点下的左子树全部搜完if(root == p) state |= 1; //表示当前子树下是存在p的:01else if(root == q) state |= 2;  //如果能找到q,则让state=2:10state |= dfs(root -> right, p, q);  //然后去搜右子树if(state == 3 && !res) res = root;  //如果为3表示当前节点下既有p又有qreturn state;}
};

记路径法:

微信截图_20250110202146.png

代码:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:bool dfs(TreeNode* cur, TreeNode* node, vector<TreeNode*>& node_path){if(!cur) return false;if(cur == node) {node_path.push_back(cur);return true;}if(dfs(cur -> left, node, node_path) || dfs(cur -> right, node, node_path)){node_path.push_back(cur);return true;}return false;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {vector<TreeNode*> pnode_path, qnode_path;dfs(root, p, pnode_path);   //找到root到p的路径dfs(root, q, qnode_path);   //找到root到q的路径//找路径的时候是从p和q往root的路径加的,所以我们翻转一下使得root在最前面reverse(pnode_path.begin(), pnode_path.end());   reverse(qnode_path.begin(), qnode_path.end());//然后取路径最短的为循环次数int n = min(pnode_path.size(), qnode_path.size());//避开当前节点p和q,然后开始从后往前倒,依次对比路径上的节点,for (int i = n - 1; i >= 0; i--)if (pnode_path[i] == qnode_path[i]) //找到它们路径第一个重合的节点return pnode_path[i];return NULL;}
};

纯享版:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {
public:bool dfs(TreeNode* cur, TreeNode* node, vector<TreeNode*>& path){if(!cur) return false;if(cur == node){path.push_back(cur);return true;}if(dfs(cur -> left, node, path) || dfs(cur -> right, node, path)){path.push_back(cur);return true;}return false;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {vector<TreeNode*> ppath, qpath;dfs(root, p, ppath);dfs(root, q, qpath);reverse(ppath.begin(), ppath.end());reverse(qpath.begin(), qpath.end());int n = min(ppath.size(), qpath.size());for(int i = n - 1; i >= 0; i--){if(ppath[i] == qpath[i]){return ppath[i];}}return NULL;}
};

LeetCode237.删除链表中的节点:

题目描述:

有一个单链表的 head,我们想删除它其中的一个节点 node。

给你一个需要删除的节点 node 。你将 无法访问 第一个节点 head。

链表的所有值都是 唯一的,并且保证给定的节点 node 不是链表中的最后一个节点。

删除给定的节点。注意,删除节点并不是指从内存中删除它。这里的意思是:

给定节点的值不应该存在于链表中。
链表中的节点数应该减少 1。
node 前面的所有值顺序相同。
node 后面的所有值顺序相同。
自定义测试:

对于输入,你应该提供整个链表 head 和要给出的节点 node。node 不应该是链表的最后一个节点,而应该是链表中的一个实际节点。
我们将构建链表,并将节点传递给你的函数。
输出将是调用你函数后的整个链表。

示例 1:

微信截图_20250111190917.png

输入:head = [4,5,1,9], node = 5
输出:[4,1,9]
解释:指定链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9

示例 2:

微信截图_20250111190924.png

输入:head = [4,5,1,9], node = 1
输出:[4,5,9]
解释:指定链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9

提示:

链表中节点的数目范围是 [2, 1000]
-1000 <= Node.val <= 1000
链表中每个节点的值都是 唯一 的
需要删除的节点 node 是 链表中的节点 ,且 不是末尾节点

思路:

狸猫换太子

因为不知道当前节点的上一个节点,如果直接删除当前节点,那么无法跟前一个节点连接,转换思路:
先将下一个节点的值赋给当前节点,再把当前节点的下一个节点删除

代码:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:void deleteNode(ListNode* node) {node -> val = node -> next -> val;node -> next = node -> next -> next;}
};

直截了当做法:

从结构体角度出发,你不是要我无法再索引到当前节点吗,那么我直接将当前节点替换为下一个节点,这样,下一个节点依然正常指向他自己的下一个节点,而当前节点相当于直接覆盖了

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:void deleteNode(ListNode* node) {*node = *node -> next;}
};

LeetCode238.除自身以外数组的乘积:

题目描述:

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

请 不要使用除法,且在 O(n) 时间复杂度内完成此题。

示例 1:

输入: nums = [1,2,3,4]
输出: [24,12,8,6]

示例 2:

输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]

提示:

2 <= nums.length <= 10^5
-30 <= nums[i] <= 30
保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内

进阶:你可以在 O(1) 的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)

思路:

题意:计算出当前数组中除当前元素之外的所有元素乘积(只能开一个数组)

对于当前元素来说,它的乘积值就是它前面的元素的乘积乘上它后面元素的乘积,所以利用前缀和思想,我们只需要求出它前面元素的乘积和它后面元素的乘积即可,但是这样的话需要开两个数组以上,题目要求只能开一个数组,那么我们需要想出优化的思路:

用一个变量S来表示从后面往前的乘积值,怎么做呢?

这里代码很优美: 就是先预处理出一个前缀乘积数组,然后从后往前开始遍历数组,s就一直叠乘数组元素,这样每遍历到一个元素就能将它前面元素的除自身意外的乘积求出来。

时间复杂度:

O(n), 只会遍历两次数组,所以时间复杂度是O(n)的

注释代码:

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();vector<int> p(n, 1);//先预处理一个前缀数组for(int i = 1; i < nums.size(); i++) p[i] = p[i - 1] * nums[i - 1];//从后往前推每个位置上的前缀*后缀,从第n-1个开始,for(int i = n - 1, s = 1; i >= 0; i--){p[i] *= s;  //当前位置的值是前缀乘后缀s *= nums[i];  //s维护的是后缀}return p;}
};

纯享版:

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();vector<int> p(n, 1);for(int i = 1; i < n; i++) p[i] = p[i - 1] * nums[i - 1];for(int i = n - 1, s = 1; i >= 0; i--){p[i] *= s;s *= nums[i];}return p;}
};

LeetCode239.滑动窗口最大值:

题目描述:

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 。

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值


[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

示例 2:

输入:nums = [1], k = 1
输出:[1]

提示:

1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
1 <= k <= nums.length

思路:

题意:滑动窗口维护数组中的k个数,当窗口填满开始,每滑动一次要输出之前的滑动窗口内数组元素的最大值。

滑动窗口最大值一般使用单调队列,而且需要支持队尾和队头都能删除,于是使用deque。
正常暴力做法是每次判断滑动窗口内的k个数哪个最大,于是需要nk的时间复杂度,使用单调队列优化,每次将滑动窗口内比当前滑入的数小的数全部清除,这样,从滑动窗口满足k个数开始,队列中存的下标都是数组元素的递减的索引,每次只需要直接返回队头就是当前滑动窗口内最大的元素了。

时间复杂度:

对于每个元素最多只会进队列一次出队列一次,总的时间复杂度为O(n)

注释代码:

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {deque<int> q;  //定义双端队列,在队vector<int> res;for(int i = 0; i < nums.size(); i++){//以i为右端点的滑动窗口,长度为k的话,左端点应该是i -k + 1//这里如果队列中队头存的下标是小于当前左端点的话,说明该数组元素被滑出滑动窗口if(q.size() && i - k  + 1 > q.front()) q.pop_front();//只要队列中还有元素并且当前准备进入的数组元素是比队尾的下标对应的数组元素大,则将队尾的元素下标去除while(q.size() && nums[i] >= nums[q.back()]) q.pop_back();//将当前下标插入队列q.push_back(i);//如果此时的i是从零开始的,所以当i>=k-1时说明此时滑动窗口开始充满k个元素了,则可以将当前滑动窗口内的最大元素(也就是队头元素)加入答案中if(i >= k - 1) res.push_back(nums[q.front()]);}return res;}
};

纯享版:

class Solution {
public:vector<int> maxSlidingWindow(vector<int>& nums, int k) {deque<int> q;vector<int> res;for(int i = 0; i < nums.size(); i++){if(q.size() && i - k + 1 > q.front()) q.pop_front();while(q.size() && nums[i] >= nums[q.back()]) q.pop_back();q.push_back(i);if(i >= k - 1) res.push_back(nums[q.front()]);}return res;}
};

LeetCode240.搜索二维矩阵Ⅱ:

题目描述:

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

每行的元素从左到右升序排列。
每列的元素从上到下升序排列。

示例 1:

微信截图_20250112200246.png

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true

示例 2:

微信截图_20250112200253.png

输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
输出:false

提示:

m == matrix.length
n == matrix[i].length
1 <= n, m <= 300
-10^9 <= matrix[i][j] <= 10^9
每行的所有元素从左到右升序排列
每列的所有元素从上到下升序排列
-10^9 <= target <= 10^9

思路:

题意:每一行从左往右都是递增的,每一列从上到下都是递减的,需要你快速从二维矩阵中找到目标值。

正常思路暴力枚举,但是时间复杂度是O(nm)的,会超时,但是这里使用脑筋急转弯式的思路:

每次找到右上角的元素,判断他是否与target相等,如果小于target,因为同一行的元素是从小到大递增的,当前右上角的元素是该行最大的元素, 都小于target说明当前第i行都是小于target的,则可以去除该行;同理,大于target则可以去除该列,下一次从下一列重新判断。

微信图片_20250112200741.png

时间复杂度:O(m + n)

注释代码:

class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {if(matrix.empty() || matrix[0].empty()) return false;int n = matrix.size(), m = matrix[0].size();int i = 0, j = m - 1;while(i < n && j >= 0){int t = matrix[i][j];  //每次从右上角判断if(t == target) return true;  //如果右上角等于target则返回true//如果大于target,同时又因为每一列都是从小往大递增,那么这一列都将大于target,可以直接将这一列去除else if(t > target) j--; //如果小于target,同时又因为每一行都是从小往大递增,当前右上角为第i行的最大值,如果这都小于target,那么这一行都将小于target,可以直接将这一行去除else i++;}return false;}
};

纯享版:

class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {if(matrix.empty() || matrix[0].empty()) return false;int n = matrix.size(), m = matrix[0].size();int i = 0, j = m - 1;while(i < n && j >= 0){int t = matrix[i][j];if(t == target) return true;else if(t > target) j--;else i++;}return false;}
};

LeetCode241.为运算表达式设计优先级:

题目描述;

给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以 按任意顺序 返回答案。

生成的测试用例满足其对应输出值符合 32 位整数范围,不同结果的数量不超过 104 。

示例 1:

输入:expression = “2-1-1”
输出:[0,2]
解释:
((2-1)-1) = 0
(2-(1-1)) = 2

示例 2:

输入:expression = “23-45”
输出:[-34,-14,-10,-10,10]
解释:
(2*(3-(45))) = -34
((2
3)-(45)) = -14
((2
(3-4))5) = -10
(2
((3-4)5)) = -10
(((2
3)-4)*5) = 10

提示:

1 <= expression.length <= 20
expression 由数字和算符 ‘+’、‘-’ 和 ‘*’ 组成。
输入表达式中的所有整数值在范围 [0, 99]
输入表达式中的所有整数都没有前导 ‘-’ 或 ‘+’ 表示符号。

思路:

题意:给出一个包含运算符的字符串,要求你设计所有组合运算结果

不能看题目是设计优先级就往优先级去考虑,这样太复杂了,这里其实本质还是求的组合方式,那么对于当前运算符而言,它的运算结果为左边所有的运算结果和右边所有运算符的所有运算结果进行一对一任意组合得到。那么以此类推我们可以利用递归将每个符号左右两边的运算结果求出。

时间复杂度:

注释代码:

class Solution {
public:vector<string> expr;vector<int> diffWaysToCompute(string s) {//将字符串拆成vectorfor(int i = 0; i < s.size(); i++){auto c = s[i];//如果是数字则将连续的数字转成整数整体再以字符串形式塞入expr中if(isdigit(c)){int x= 0, j = i;while(j < s.size() && isdigit(s[j])) x = x * 10 + (s[j++] - '0');expr.push_back(to_string(x));i = j - 1;}else expr.push_back(s.substr(i, 1));  //如果是运算符则直接放入}return dfs(0, expr.size() -1);  //}//搜索的是从l到r范围内的所有运算路径vector<int> dfs(int l, int r){if(l == r) return {stoi(expr[l])};vector<int> res;for(int i = l + 1;  i < r; i+= 2)  //每次跳两个,因为“数字 (运算符) 数字”{//分别求左边的所有运算方式和右边的所有运算方式auto left = dfs(l, i - 1), right = dfs(i + 1, r);//从左边所有运算方式和右边所有运算方式中各任选一种进行搭配成当前符号左右两边的运算值for(auto x : left){for(auto y : right){int z;if(expr[i] == "+") z = x + y;else if(expr[i] == "-") z = x - y;else if(expr[i] == "*") z = x * y;else z = x / y;res.push_back(z);  //将当前符号的所有运算方式加入res中}}}return res;  }
};

纯享版:

class Solution {
public:vector<string> expr;vector<int> diffWaysToCompute(string s) {for(int i = 0; i < s.size(); i++){if(isdigit(s[i])){auto x = 0, j = i;while(j < s.size() && isdigit(s[j])) x = x * 10 + (s[j++] - '0');expr.push_back(to_string(x));i = j - 1;}else expr.push_back(s.substr(i, 1));}return dfs(0, expr.size() - 1);}vector<int> dfs(int l, int r){vector<int> res;if(l == r) return {stoi(expr[l])};for(int i = l + 1; i < r; i+= 2){auto left = dfs(l, i - 1), right = dfs(i + 1, r);for(auto x : left){for(auto y : right){int z;if(expr[i] == "-") z = x - y;else if(expr[i] == "+") z = x + y;else if(expr[i] == "*") z = x * y;res.push_back(z);}}}return res;}
};

LeetCode242.有效的字母异位词:

题目描述:

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的
字母异位词

示例 1:

输入: s = “anagram”, t = “nagaram”
输出: true

示例 2:

输入: s = “rat”, t = “car”
输出: false

提示:

1 <= s.length, t.length <= 5 * 10^4
s 和 t 仅包含小写字母

进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

思路: 存两个hash表比较是否一致

代码:

class Solution {
public:bool isAnagram(string s, string t) {unordered_map<char, int> a, b;for(auto c : s) a[c]++;for(auto c : t) b[c]++;return a == b;}
};

LeetCode257.二叉树的所有路径:

题目描述:

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

示例 1:

输入:root = [1,2,3,null,5]
输出:[“1->2->5”,“1->3”]

示例 2:

输入:root = [1]
输出:[“1”]

提示:

树中节点的数目在范围 [1, 100] 内
-100 <= Node.val <= 100

思路:二叉树爆搜模板题

时间复杂度:O(n*n)

注释代码:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<string> res;vector<int> path;vector<string> binaryTreePaths(TreeNode* root) {if(root) dfs(root);return res;}void dfs(TreeNode* root){path.push_back(root -> val);if(!root -> left && !root -> right){string line = to_string(path[0]);for(auto i = 1; i < path.size(); i++){line += "->" + to_string(path[i]);}res.push_back(line);}else{if(root -> left) dfs(root -> left);if(root -> right) dfs(root -> right);}path.pop_back();}
};

纯享版:


LeetCode2458.各位相加:

题目描述:

给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。返回这个结果。

示例 1:

输入: num = 38
输出: 2
解释: 各位相加的过程为:
38 --> 3 + 8 --> 11
11 --> 1 + 1 --> 2
由于 2 是一位数,所以返回 2。
示例 2:

输入: num = 0
输出: 0

提示:

0 <= num <= 2^31 - 1

进阶:你可以不使用循环或者递归,在 O(1) 时间复杂度内解决这个问题吗?

思路:

微信截图_20250114165906.png

代码:

class Solution {
public:int addDigits(int num) {if(num == 0) return 0;if(num % 9) return num % 9;return 9;}
};
http://www.dtcms.com/a/343407.html

相关文章:

  • 深入解析JUC线程间通信:使用ReentrantLock与Condition实现精准线程调度
  • 32、智能仓库管理与优化系统 (模拟) - /物流与仓储组件/warehouse-optimization-system
  • IPSec 与 IKE 核心知识点总结
  • 使用Python 创建虚拟环境的两种方式
  • 订单簿数据深度学习方法在大单发现应用
  • 让医学数据更直观——MedCalc 23.1.7 最新版使用体验
  • sageattention低比特量化注意力机制,比FlashAttention快5 倍
  • DeepSeek-V3.1 Claude Code: 革命性的AI编码助手详解与应用指南
  • 论文图片在要求dpi下,压缩尺寸
  • ES_预处理
  • java18学习笔记-Simple Web Server
  • 美国联邦调查局警告俄罗斯针对思科设备的网络间谍活动
  • 残差神经网络(ResNet)
  • 矫平机与纵剪:一条钢卷“变身”的全过程
  • 【UE5-Airsim】Windows10下安装UE5-Airsim的仿真环境
  • leetcode 1658 将x减到0的最小操作数
  • 同题异构解决leetcode第3646题下一个特殊回文数
  • Linux网络socket套接字(上)
  • linux 之virtio 的驱动框架
  • Motocycle 智能仪表盘
  • 白光干涉测量系统的复合相移三维重建和多视场形貌拼接的复现
  • 【自然语言处理与大模型】微调与RAG的区别
  • JavaScript基础语法five
  • 【Protues仿真】基于AT89C52单片机的数码管驱动事例
  • 力扣905:按奇偶排序数组
  • 2025-08-21 Python进阶4——错误和异常
  • 开发者中使用——控制台打印数据
  • 爬虫基础学习-基本原理和GET请求
  • JavaScript 基本语法
  • 智慧城市SaaS平台/市政设施运行监测系统之空气质量监测系统、VOC气体监测系统、污水水质监测系统及环卫车辆定位调度系统架构内容