《双指针算法指南:LeetCode 经典题解(C++实现)》
《双指针算法指南:LeetCode 经典题解(C++实现)》
—— 从快慢指针到对撞指针,刷题效率提升 200%!
常⻅的双指针有两种形式,⼀种是对撞指针,⼀种是左右指针。
对撞指针:
⼀般⽤于顺序结构中,也称左右指针。
-
对撞指针从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼近。
-
对撞指针的终⽌条件⼀般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出循环),也就是:
left == right (两个指针指向同⼀个位置)
left > right (两个指针错开)
快慢指针:
又称为龟兔赛跑算法,其基本思想就是使⽤两个移动速度不同的指针在数组或链表等序列结构上移动。
这种⽅法对于处理环形链表或数组⾮常有⽤。
其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使⽤快慢指针的思想。快慢指针的实现⽅式有很多种,最常⽤的⼀种就是:
• 在⼀次循环中,每次让慢的指针向后移动⼀位,⽽快的指针往后移动两位,实现⼀快⼀慢。
移动零(easy)
「数组分两块」是⾮常常⻅的⼀种题型,主要就是根据⼀种划分⽅式,将数组的内容分成左右两部分。这种类型的题,⼀般就是使⽤「双指针」来解决。
题⽬链接:
283. 移动零
要点:
- 保持非零元素的相对顺序
- 空间复杂度需为 O(1)
- 通过双指针将数组分为已处理区(非零)和未处理区
老师代码:
class Solution
{
public:void moveZeroes(vector<int>& nums){for(int cur = 0, dest = -1; cur < nums.size(); cur++)if(nums[cur]) // 处理⾮零元素swap(nums[++dest], nums[cur]);}
}
老师思路:
- 「数组分两块」是⾮常常⻅的⼀种题型,主要就是根据⼀种划分⽅式,将数组的内容分成左右两部分。这种类型的题,⼀般就是使⽤「双指针」来解决
- 在本题中,我们可以⽤⼀个 cur 指针来扫描整个数组,另⼀个 dest 指针⽤来记录⾮零数序列的最后⼀个位置。根据 cur 在扫描的过程中,遇到的不同情况,分类处理,实现数组的划分。 在 cur 遍历期间,使 [0, dest] 的元素全部都是⾮零元素, [dest + 1, cur - 1] 的元素全是零
我的代码:
class Solution {
public:void moveZeroes(vector<int>& nums) {int dest = -1;//指向已经移动完成的区域的最后一个位置int cur = 0;//指向当前需要操作的位置while(cur < nums.size()){if(nums[cur] == 0){cur++;}else{std::swap(nums[dest + 1], nums[cur]);dest++;cur++;}}}
};
我的思路:
使用 dest
指针标记已处理非零元素的末尾,cur
指针遍历数组。当 cur
遇到非零元素时,与 dest+1
位置交换,dest
后移。此操作保证 [0, dest]
始终为非零元素,时间复杂度 O(n)。
我的笔记:
-
dest
初始化为 -1,巧妙处理初始边界 -
交换操作后只需
dest++
,无需重复检查已处理区域 -
对比老师的代码,发现
for
循环比while
更简洁,但逻辑等价
复写零
题⽬链接:
复写零
要点:
- 原地修改数组
- 从后向前复写避免覆盖未处理数据
- 需处理连续零导致数组越界的情况
老师代码:
class Solution
{
public:void duplicateZeros(vector<int>& arr){// 1. 先找到最后⼀个数int cur = 0, dest = -1, n = arr.size();while(cur < n){if(arr[cur]) dest++;else dest += 2;if(dest >= n - 1) break;cur++;}// 2. 处理⼀下边界情况if(dest == n){arr[n - 1] = 0;cur--; dest -=2;}// 3. 从后向前完成复写操作while(cur >= 0){if(arr[cur]) arr[dest--] = arr[cur--];else{arr[dest--] = 0;arr[dest--] = 0;cur--;}}}
}
老师思路:
如果「从前向后」进⾏原地复写操作的话,由于 0 的出现会复写两次,导致没有复写的数「被覆盖掉」。因此我们选择「从后往前」的复写策略。但是「从后向前」复写的时候,我们需要找到「最后⼀个复写的数」,因此我们的⼤体流程分两步:i. 先找到最后⼀个复写的数;ii. 然后从后向前进⾏复写操作
我的代码:
class Solution {
public:void duplicateZeros(vector<int>& arr) {int dest = -1, cur = 0, n = arr.size();while(cur < n)//用快慢双指针来找到最后一个可以复写到的元素,标记为cur{if(arr[cur]) dest++;else dest +=2;if(dest >= n - 1) break;cur++;}if(dest == n)//如果dest出现越界,则cur指向的位置一定是0{arr[n - 1] = 0;//复写后的最后一个数字为0dest -= 2;//回退到n-2cur--;//回退一格}while(cur >= 0)//从后往前遍历复写{if(arr[cur]) arr[dest--] = arr[cur--];else {arr[dest--] = 0;arr[dest--] = 0;cur--;}}}
};
我的思路:
- 模拟填充:先用快慢指针找到最后一个有效元素的位置
- 边界修正:若模拟填充时
dest
越界,需手动处理末尾零 - 逆向复写:从后往前填充,遇到零则复写两次
我的笔记:
- 注意边界情况
dest
的移动规则:遇到非零+1,遇到零+2- 逆向复写时,
cur
指针的起始位置需通过模拟填充确定 - 边界条件
dest == n
表示最后一个有效元素是零且导致越界
快乐数
题⽬链接:
快乐数
要点:
- 无限循环的两种形式:循环到1或在其他数循环
- 快慢指针可检测循环存在
老师代码:
class Solution
{
public:int bitSum(int n) // 返回 n 这个数每⼀位上的平⽅和{int sum = 0;while(n){int t = n % 10;sum += t * t;n /= 10;}return sum;}bool isHappy(int n){int slow = n, fast = bitSum(n);while(slow != fast){slow = bitSum(slow);fast = bitSum(bitSum(fast));}return slow == 1;}
}
老师思路:
为了⽅便叙述,将「对于⼀个正整数,每⼀次将该数替换为它每个位置上的数字的平⽅和」这⼀个操作记为 x 操作; 题⽬告诉我们,当我们不断重复 x 操作的时候,计算⼀定会「死循环」,死的⽅式有两种:
▪ 情况⼀:⼀直在 1 中死循环,即 1 -> 1 -> 1 -> 1…
▪ 情况⼆:在历史的数据中死循环,但始终变不到 1 由于上述两种情况只会出现⼀种,因此,只要我们能确定循环是在「情况⼀」中进⾏,还是在「情况⼆」中进⾏,就能得到结果。
简单证明:a. 经过⼀次变化之后的最⼤值 9^2 * 10 = 810 ( 2^31-1=2147483647 。选⼀个更⼤的最⼤ 9999999999 ),也就是变化的区间在 [1, 810] 之间; b. 根据「鸽巢原理」,⼀个数变化 811 次之后,必然会形成⼀个循环; c. 因此,变化的过程最终会⾛到⼀个圈⾥⾯,因此可以⽤「快慢指针」来解决
根据上述的题⽬分析,我们可以知道,当重复执⾏ x 的时候,数据会陷⼊到⼀个「循环」之中。 ⽽「快慢指针」有⼀个特性,就是在⼀个圆圈中,快指针总是会追上慢指针的,也就是说他们总会相遇在⼀个位置上。如果相遇位置的值是 1 ,那么这个数⼀定是快乐数;如果相遇位置不是 1 的话,那么就不是快乐数
我的代码:
class Solution {
public:int fun(int x){int a = 1, sum = 0;while(x / a >= 10){sum += (x % (a * 10) / a) * (x % (a * 10) / a);a *= 10;}sum += (x / a) * (x / a);return sum;}bool isHappy(int n) {int fast = n, slow = n;do{fast = fun(fast);fast = fun(fast);slow = fun(slow);}while(fast != slow);if(fast == 1) return true;else return false;}};
我的思路:
- 定义
fast
和slow
指针,fast
每次计算两次平方和,slow
一次 - 若两指针相遇且值为1,则是快乐数;否则存在非1循环
我的笔记:
-
要学会老师取一个整数的每一位数的方法
-
简化代码
-
当提到无限循环的时候就要想到能不能用快慢双指针的方法解决问题,就像链表成环问题一样
-
平方和函数可用取余法优化:
while(n) { t = n%10; sum += t*t; n /=10; }
-
快慢指针相遇后只需判断是否为1,无需继续计算
-
时间复杂度从 O(n) 降至 O(logn)
盛水最多的容器
题⽬链接:
盛水最多的容器
要点:
- 容积公式:
min(height[left], height[right]) * (right - left)
- 移动较短指针可能获得更大容积
老师代码:
class Solution
{
public:int maxArea(vector<int>& height){int left = 0, right = height.size() - 1, ret = 0;while(left < right){int v = min(height[left], height[right]) * (right - left);ret = max(ret, v);// 移动指针if(height[left] < height[right]) left++;else right--;}return ret;}
}
老师思路:
我的代码:
class Solution {
public:int maxArea(vector<int>& height) {int left = 0, right = height.size() - 1;int max = 0, maxi = 0; while(left < right){maxi = (right - left) * (height[left] < height[right] ? height[left] : height[right]);max = max > maxi ? max : maxi; if(height[left] < height[right]){left++;}else{right--;}}return max;}
};
我的思路:
从两端往中间靠拢的过程中,长度一直在减少,因此要想找到比现在还大的容积只有当高度比现在指针指向的高度还要高的情况才有可能出现,因此才有了上面的判断条件
我的笔记:
- 使用函数max() 和min()
- 贪心思想的典型应用
- 即使移动后高度可能降低,但宽度减少的损失已被提前计算
- 时间复杂度 O(n),优于暴力法的 O(n²)
有效三角形个数
题⽬链接:
有效三角形个数
要点:
- 三角形判定:两边之和大于第三边
- 排序后固定最大边,双指针找有效组合
老师代码:
class Solution
{
public:int triangleNumber(vector<int>& nums){// 1. 优化sort(nums.begin(), nums.end());// 2. 利⽤双指针解决问题int ret = 0, n = nums.size();for(int i = n - 1; i >= 2; i--) // 先固定最⼤的数{// 利⽤双指针快速统计符合要求的三元组的个数int left = 0, right = i - 1;while(left < right){if(nums[left] + nums[right] > nums[i]){ret += right - left;right--;}else{left++;}}}return ret;}
};
老师思路:
我的代码:
class Solution {
public:int triangleNumber(vector<int>& nums) {sort(nums.begin(), nums.end());int num = 0;int hight = nums.size() - 1, left = 0, right = hight - 1;while(hight >= 2){while(left < right){if(nums[left] + nums[right] > nums[hight]){num += right - left;right--;}else{left++;}}hight--;left = 0, right = hight - 1;}return num;}
};
我的思路:
- 排序数组,逆序枚举最大边
nums[i]
- 双指针
left=0
和right=i-1
搜索满足nums[left] + nums[right] > nums[i]
的组合 - 若满足条件,则
right-left
个组合均有效
我的笔记:
- 排序算法,已经使用模版了,所以只需要使用模版中的排序算法就行了
- 排序时间复杂度 O(nlogn) 主导整体效率
- 双指针将内层循环从 O(n²) 优化到 O(n)
- 关键代码逻辑:
if (sum > target) ret += right - left;
和为 s 的两个数字
题⽬链接:
和为 s 的两个数字
要点:
老师代码:
class Solution
{
public:vector<int> twoSum(vector<int>& nums, int target){int left = 0, right = nums.size() - 1;while(left < right){int sum = nums[left] + nums[right];if(sum > target) right--;else if(sum < target) left++;else return {nums[left], nums[right]};}// 照顾编译器return {-4941, -1};}
}
我的代码:
class Solution {
public:vector<int> twoSum(vector<int>& price, int target) {//vector<int> nums = {0, 0};int left = 0, right = price.size() - 1;while(left < right){if(price[left] + price[right] == target){//nums[0] = price[left], nums[1] = price[right];return {price[left], price[right]};}else if(price[left] + price[right] > target){right--;}else{left++;}}//return nums;return {0, 0};}
};
我的思路:
我的笔记:
- 这里使用了一个大括号的隐式类型转换
三数之和
题⽬链接:
三数之和
要点:
- 去重是关键:固定数、左指针、右指针均需跳过重复值
- 排序后使用双指针将时间复杂度从 O(n³) 降至 O(n²)
老师代码:
class Solution
{
public:vector<vector<int>> threeSum(vector<int>& nums){vector<vector<int>> ret;// 1. 排序sort(nums.begin(), nums.end());// 2. 利⽤双指针解决问题int n = nums.size();for(int i = 0; i < n; ) // 固定数 a{if(nums[i] > 0) break; // ⼩优化int left = i + 1, right = n - 1, target = -nums[i];while(left < right){int sum = nums[left] + nums[right];if(sum > target) right--;else if(sum < target) left++;else{ret.push_back({nums[i], nums[left], nums[right]});left++, right--;// 去重操作 left 和 rightwhile(left < right && nums[left] == nums[left - 1]) left++;while(left < right && nums[right] == nums[right + 1]) right--;}}// 去重 ii++;while(i < n && nums[i] == nums[i - 1]) i++;}return ret;}
};
我的代码:
错误一
#include <vector>
class Solution {
private:vector<vector<int>> arr;
public:vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(), nums.end());int heigh = nums.size() - 1, left = 0, right = heigh - 1;while(heigh >= 2){while(left < right){if(nums[left] + nums[right] + nums[heigh] > 0){while(right - 1 > 0 && nums[right - 1] == nums[right]){right--;}right--;}else if(nums[left] + nums[right] + nums[heigh] < 0){while(left + 1 < heigh && nums[left + 1] == nums[left]){left++;}left++;}else{arr.push_back({nums[left], nums[right], nums[heigh]});left++, right--;}}left = 0, right = heigh - 1;while(heigh >= 2 && nums[heigh - 1] == nums[heigh])heigh--;heigh--;}return arr;}
};
错误二:
class Solution {
private:vector<vector<int>> arr;
public:vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(), nums.end());for(int a = 0; a < nums.size();){int left = a + 1, right = nums.size() - 1;while(left < right){if(nums[left] + nums[right] + nums[a] == 0){arr.push_back({nums[a], nums[left], nums[right]});left++;//这里同样需要判断是否越界,这是错误原因right--;}else if(nums[left] + nums[right] + nums[a] > 0){right--;while(left < right && nums[right + 1] == nums[right]) right--;//这段代码写到上面批注部分}else{left++;while(left < right && nums[left - 1] == nums[left]) left++;//这段代码也写到上面批注部分}}a++;while(a < nums.size() && nums[a - 1] == nums[a]) a++;} return arr;}
};
我的思路:
要点:
-
算法思:双指针思想
先排序
然后固定⼀个数 a
在这个数后⾯的区间内,使⽤「双指针算法」快速找到两个数之和等于 -a 即可 (这一条只要满足题意都可以)
-
注意:
找到⼀个结果之后, left 和 right 指针要「跳过重复」的元素;
使⽤完⼀次双指针算法之后,固定的 a 也要「跳过重复」的元素
越界判断
-
固定第一个数
nums[i]
,转化为两数之和问题 -
双指针
left=i+1
和right=n-1
搜索target = -nums[i]
-
去重操作需在找到解后立即执行
我的笔记:
-
我提交的代码是有一些无法通过的,其实就是边界问题没有处理好,如:
while(left < right && nums[right - 1] == nums[right])//这里是吧现在这个nums[right],与数组的下一个nums[right - 1]对比 {right--; } right--;//如果使用这一种方法,这一条代码执行后就不能判断right是否越界了
将这一串代码的判断条件换一个方法:
right--; while(left < right && nums[right + 1] == nums[right])//这里是吧现在这个nums[right],与数组的上一个nums[right + 1]对比 {right--; }
就可以完美解决无法判断后面right–;是否越界的情况
-
注意去重与越界访问问题,以后写代码都要记得考虑一下这个问题
-
去重代码模板:
while (i < n && nums[i] == nums[i-1]) i++; // 外层去重 while (left < right && nums[left] == nums[left-1]) left++; // 内层去重
-
边界检查
left < right
必须放在条件首位,防止越界
四数之和
题⽬链接:
四数之和
要点:
- 在三数之和基础上增加一层循环
- 使用
long long
防止整数溢出
老师代码:
class Solution
{
public:vector<vector<int>> fourSum(vector<int>& nums, int target){vector<vector<int>> ret;// 1. 排序sort(nums.begin(), nums.end());// 2. 利⽤双指针解决问题int n = nums.size();for(int i = 0; i < n; ) // 固定数 a{// 利⽤ 三数之和for(int j = i + 1; j < n; ) // 固定数 b{// 双指针int left = j + 1, right = n - 1;long long aim = (long long)target - nums[i] - nums[j];while(left < right){int sum = nums[left] + nums[right];if(sum < aim) left++;else if(sum > aim) right--;else{ret.push_back({nums[i], nums[j], nums[left++],nums[right--]});// 去重⼀while(left < right && nums[left] == nums[left - 1])left++;while(left < right && nums[right] == nums[right + 1])right--;}}// 去重⼆j++;while(j < n && nums[j] == nums[j - 1]) j++;}// 去重三i++;while(i < n && nums[i] == nums[i - 1]) i++;}return ret;}
};
我的代码:
class Solution {
private:vector<vector<int>> arr;
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {sort(nums.begin(), nums.end());for(int i = 0; i < nums.size();){for(int j = i + 1; j < nums.size();){int left = j + 1, right = nums.size() - 1;while(left < right){long long num = (long long)nums[i] + nums[j] + nums[left] + nums[right];if(num == target){arr.push_back({nums[i], nums[j], nums[left], nums[right]});left++, right--;//去重一while(left < right && nums[left] == nums[left - 1]) left++;while(left < right && nums[right] == nums[right + 1]) right--;}else if(num > target) right--;else left++;}//去重二j++;while(j <nums.size() && nums[j] == nums[j - 1]) j++;}//去重三i++;while(i < nums.size() && nums[i] == nums[i - 1]) i++;} return arr;}
};
我的思路:
- 双重循环固定前两个数
nums[i]
和nums[j]
- 双指针
left=j+1
和right=n-1
搜索剩余两数- 每层循环均需去重
我的笔记:
- 去重:与前面的三数之和是一样的,去重时要考虑边界问题
- 边界问题:不去重的时候也要注意边界问题
- 这个题目在计算时会有数据溢出的风险,因此代码中用到了long long,此时在计算时算式的右边第一个变量也要强转成long long 类型
- 溢出处理:
long long aim = (long long)target - nums[i] - nums[j];
- 去重逻辑与三数之和一致,需在每层循环后跳过重复值
- 时间复杂度 O(n³),但实际运行效率较高
相关文章:
《双指针算法指南:LeetCode 经典题解(C++实现)》
《双指针算法指南:LeetCode 经典题解(C实现)》 —— 从快慢指针到对撞指针,刷题效率提升 200%! 常⻅的双指针有两种形式,⼀种是对撞指针,⼀种是左右指针。 对撞指针: ⼀般⽤于顺…...
kaggle上经典泰坦尼克项目数据分析探索
之前了解在kaggle上这个项目很火,最近想要加强一下python数据分析,所以在kaggle上找到这个项目进行学习探索,下面是将一些学习资料以及过程整理出来。 一、首先我们了解一下项目背景以及如何找到这个项目。 kaggle项目地址: https://www.k…...
【深度学习】多目标融合算法(五):定制门控网络CGC(Customized Gate Control)
目录 一、引言 二、CGC(Customized Gate Control,定制门控网络) 2.1 技术原理 2.2 技术优缺点 2.3 业务代码实践 2.3.1 业务场景与建模 2.3.2 模型代码实现 2.3.3 模型训练与推理测试 2.3.4 打印模型结构 三、总结 一、引言 上一…...
Ubuntu上查看GPU使用情况并释放内存
先用nvidia-smi查看GPU当前使用情况 再用fuser 命令查找对应显卡上占用 GPU 的进程 最后查到了用kill -9强制杀掉进程(PID)即可...
大数据学习栈记——HBase安装
本文介绍大数据技术中流行的非关系型数据库HBase的安装,操作系统:Ubuntu24.04 安装Zookeeper 安装HBase前需要先安装Zookeeper,HBase使用Zookeeper作为其分布式协同服务,存储了HBase集群的元数据信息,并提供了分布式…...
[入门]NUC13配置Ubuntu20.04详细步骤
文章目录 1. 安装Ubuntu20.041.1 制作系统启动盘1.1.1 下载镜像文件1.1.2 配置启动盘 1.2 安装内存条、硬盘1.3 安装系统 2. 网卡驱动配置2.1 关闭安全启动2.2 安装intel官方网卡驱动backport2.2.1 第四步可能会出现问题 2.3 ubuntu官方的驱动2.4 重启 3. 软件安装3.1 录屏软件…...
【实战指南】用MongoDB存储文档和图片等大文件(Java实现)
一、前言 在现代应用开发中,经常需要处理和存储大量的文档、图片等大文件。传统的关系型数据库在处理这类大文件时,往往会面临性能瓶颈、存储成本高等问题。而 MongoDB 作为一款流行的 NoSQL 数据库,提供了 GridFS 规范,能够很好地解决大文件存储的问题。GridFS 可以将大文…...
使用Gitee Go流水线部署个人项目到服务器指南
使用Gitee Go流水线部署个人项目到服务器指南 前言!!! 本文解决的问题: 你有一台ECS服务器,你在上面部署了一个Java服务也就是一个jar,你觉着你每次手动本地打包,上传,在通过命令去…...
使用Three.js渲染器创建炫酷3D场景
引言 在当今数字化的时代,3D图形技术正以其独特的魅力在各个领域掀起波澜。从影视制作到游戏开发,从虚拟现实到网页交互,3D场景以其强烈的视觉冲击力和沉浸式的体验,成为了吸引用户、传达信息的重要手段。而Three.js,…...
Spring Boot 集成 Elasticsearch怎样在不启动es的情况下正常启动服务
解释 在spingboot 集成es客户端后,每当服务启动时,服务默认都会查看es中是否已经创建了对应的索引,如果没有索引则创建。基于上面的规则我们可以通过配置不自动创建索引来达到在没有es服务的情况下正常启动服务。 解决办法 在entity类的Docu…...
明远智睿SD2351核心板:多接口融合,破解边缘计算难题
在边缘计算领域,明讯智睿SD2351核心板凭借丰富的接口资源与异构计算架构,成为工业网关与智能终端的理想选择。硬件配置升级 :处理器:四核Cortex-A35,256KB L2缓存,动态调频降低功耗;存储性能:emMC 5.0 HS400模式读写速度提升40%&a…...
xampp安装教程与配置
一、安装 XAMPP (一)下载 访问官网:打开浏览器,访问 XAMPP 官方网站(https://www.apachefriends.org/zh_cn/index.html)。 选择版本:根据你的操作系统(Windows、macOS 或 Linux&am…...
设计模式之单例模式(Singleton Pattern)
单例模式(Singleton Pattern)是一种常用的设计模式,确保一个类只有一个实例,并提供一个全局访问点。单例模式在许多场景中非常有用,例如配置管理、日志记录、线程池等。 ### **1. 单例模式的特点** 1. **唯一实例**&a…...
Androidstudio实现引导页文字动画
文章目录 1. 功能需求2. 代码实现过程1. 编写布局文件2. 实现引导页GuideActivity 3. 总结4. 效果演示5. 关于作者其它项目视频教程介绍 1. 功能需求 1、引导页具有两行文字(“疫情在前”和“共克时艰”),和向上的 图标。 2、进入【引导页】…...
【linux】线程概念与控制
引言 当现代CPU的晶体管密度逼近物理极限,多核架构已成为突破性能瓶颈的必由之路。在这个计算密集型任务与异步IO需求并行的时代,多线程编程不再是可选项,而是开发者必须掌握的核心技能。Linux作为承载着全球90%云计算负载的操作系统…...
Cesium 自定义路径导航材质
cesium 自定义路径导航纹理图片随便更换,UI 提供设计图片即可达到效果; 打开小马的weix 关注下 搜索“技术链” 回复关键词《《路径》》获取原始代码; 拿到就能用轻松解决!帮忙点个关注吧!...
用 pytorch 从零开始创建大语言模型(五):预训练无标注数据
用 pytorch 从零开始创建大语言模型(五):预训练无标注数据 5 预训练无标注数据5.1 评估文本生成模型5.1.1 使用 GPT 生成文本5.1.2 计算文本生成损失5.1.3 计算训练集和验证集的损失 5.2 训练 LLM5.3 解码策略以控制随机性5.3.1 温度缩放&am…...
[AI速读]混合验证方案:如何高效解决RISC-V向量扩展的验证难题
RISC-V作为一种开源指令集架构,近年来在AI和高性能计算领域备受关注。其向量扩展(RVV)为处理并行数据提供了强大的支持,但复杂的异常处理和冒险检测机制也带来了验证上的巨大挑战。本文将结合一篇技术论文,解析一种混合验证方案,帮助开发者更高效地解决RVV的验证问题。 一…...
模型空间、图纸空间、布局(Layout)之间联系——CAD c#二次开发
在 AutoCAD 的二次开发中,**模型空间(Model Space)**、**图纸空间(Paper Space)** 和 **布局(Layout)** 是三个核心概念,它们的关系及开发中的操作逻辑如下: --- 1. 模…...
Linux 日常开发常用命令(解释-全)
帮助类 #查看cd命令的帮助信息 [rootcentos100 ~] help cd # 查看网卡配置信息 [rootcentos100 ~] ifconfig # 检测到目标主机是否连接正常 [rootcentos100 ~] ping IP地址[rootcentos100 ~] ssh [-p port] userremote #远程登录user 是在远程机器上的用户名,如果…...
数据库监控:确保业务连续性和用户体验
在数字化时代,数据库作为企业的数据心脏,其重要性不言而喻。无论是交易系统、客户关系管理系统,还是数据分析平台,都离不开数据库的支撑。然而,数据库的运行状态和性能直接影响着企业的业务连续性和用户体验。因此&…...
Java面试黄金宝典9
1. Redis 持久化机制 Redis 提供了两种主要的持久化机制:RDB(Redis Database)和 AOF(Append Only File),下面对这两种机制进行详细介绍。 RDB(Redis Database) 原理:RDB …...
【C#】WinForm自定义控件及窗体
前言 WinForm(Windows Forms)是Microsoft.NET框架中的技术,用于开发Windows桌面应用程序。它提供了一套丰富的控件和组件。通过拖放控件、编写事件处理程序等方式快速构建用户界面。 通过属性窗口定制这些控件的外观和行为。 通过数据绑定&am…...
VideoHelper 油猴脚本,重塑你的视频观看体验
VideoHelper 油猴脚本,重塑你的视频观看体验 在日常上网看视频时,你是否也被这些问题困扰:视频网站开头的广告又臭又长,找个合适的播放倍速要在一堆选项里翻半天,每次手动调音量、点全屏按钮繁琐又影响沉浸感…...
从收藏夹到知识图谱:书签管理器如何重塑你的信息获取方式?
在信息爆炸的今天,浏览器收藏夹早已沦为 “数字垃圾堆”—— 杂乱无章的网址、重复的标签、过期的链接,不仅降低效率,更成为信息焦虑的源头。智能书签管理器通过AI分类、跨平台同步、隐私保护等黑科技,重塑您的数字生活方式。书签…...
SOFABoot-07-版本查看
前言 大家好,我是老马。 sofastack 其实出来很久了,第一次应该是在 2022 年左右开始关注,但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFABoot-00-sofaboot 概览 SOFABoot-01-蚂蚁金服开源的 s…...
[极客大挑战 2019]Http_3.19BUUCTF练习day3(1)
BUUCTF练习day3(1)_[极客大挑战 2019]Http 打开靶场,查看源码(如果在做题时没有什么发现就查看源码) 打开Secret.php提示没有来自https://Sycsecret.buuoj.cn 添加Referer头为https://Sycsecret.buuoj.cn(提示说我们没有来自那个网址,那我们…...
golang Error的一些坑
golang Error的一些坑 golang error的设计可能是被人吐槽最多的golang设计了。 最经典的err!nil只影响代码风格设计,而有一些坑会导致我们的程序发生一些与我们预期不符的问题,开发过程中需要注意。 errors.Is判断error是否Wrap不符合预期 …...
弱网测试:全链路实战、高阶策略与自动化落地
在移动互联网时代,网络环境的不确定性成为用户体验的“隐形杀手”。弱网测试不仅是质量保障的必备环节,更是提升用户留存率和业务转化率的战略手段。 本文将从 工具链深度配置、复杂场景模拟、性能优化底层逻辑 和 自动化流水线集成 四个维度,彻底解析弱网测试的完整方法论…...
Ubuntu检查并启用 Nginx 的stream模块或重新安装支持stream模块的Nginx
stream 模块允许 Nginx 处理 TCP 和 UDP 流量,常用于负载均衡和端口转发等场景。本文将详细介绍如何检查 Nginx 是否支持 stream 模块,以及在需要时如何启用该模块。 1. 检查 Nginx 是否支持 stream 模块 首先,需要确认当前安装的 Nginx 是…...
mac brew 安装的php@7.4 打开redis扩展
1. 找到php7.4的pecl目录 一般在这个位置 cd /usr/local/Cellar/php7.4/7.4.33_8/pecl/20190902 ls 一下 有个 redis.so 于是 直接去php.ini编辑了 php.ini的路径 vim /usr/local/etc/php/7.4/php.ini 把938行添加进去 然后重启一下 php7.4 brew services restart ph…...
Redis 内存管理
Redis 内存管理 1. Redis 给缓存数据设置过期时间的作用 给缓存数据设置过期时间(TTL, Time-To-Live)有以下几个重要作用: (1) 自动释放内存 避免缓存数据无限增长,导致 Redis 内存溢出。例如,在 会话管理、短连接…...
学习CSS滤镜属性 `filter: invert()`
一、核心机制 数学原理 invert(1) 对每个像素的RGB通道执行 颜色反相计算: 新通道值 255 - 原通道值 例如 rgb(255,0,0)(纯红)会转换为 rgb(0,255,255)(青色)。 透明度处理 该滤镜会保留元素的Alpha通道(…...
网络空间安全专业发展历程及开设院校
一、专业发展历程 1. 早期探索阶段(1990年代末—2000年代初) (1)背景: 1990年代互联网进入中国,计算机病毒、黑客攻击等问题逐渐显现,社会对信息安全人才的需求开始萌芽。 (2&…...
Linux中mutex机制
在Linux中,mutex是一种用于多线程编程的同步机制,用于保护共享资源,防止多个线程同时访问或修改这些资源,从而避免竞态条件的发生。mutex 是“mutual exclusion”的缩写,意为“互斥”。 1. Mutex 的基本概念 互斥锁&…...
Web网页
1.结构与表现分离 HTML用于结构 css用于表现,增加了丰富的样式效果,极大满足了开发者的需求 选择器;用于指定css样式作用的html对象{}选择某个属性 p标签 color;本颜色 font-size:子属性 字大小 font-family;字体 font-…...
Redis 在windows下的下载安装与配置
参考链接:https://developer.aliyun.com/article/1395346 下载 Redis 访问 Redis 下载地址:https://github.com/tporadowski/redis/releases 下载 Redis 时,你可以选择 ZIP 包或 MSI 安装: ZIP包:需要手动解压、初始化、配置和…...
基于随机森林回归预测葡萄酒质量
基于随机森林回归预测葡萄酒质量 1.作者介绍2.随机森林算法与数据集介绍2.1定义2.2核心思想2.3主要步骤2.4数据集介绍 3.算法实现3.1数据加载与探索3.2数据可视化3.3数据预处理(标准化、划分训练/测试集)3.4模型训练与优化(随机森林回归 超参…...
在大数据开发中ETL是指什么?
hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在数字经济时代,数据已成为企业最核心的资产。然而,分散在业务系统、日志文件…...
Centos操作系统安装及优化
Centos操作系统安装及优化 零、环境概述 主机名 centos版本 cpu 内存 Vmware版本 ip地址 test CentOS Linux release 7.6.1810 (Core) 2C 2G 15.5.1 10.0.0.10 一、介质下载 1、7.6版本下载 CentOS7.6标准版下载链接: https://archive.kernel.org/centos-vault/7.6.1810/i…...
2025年03月10日人慧前端面试(外包滴滴)
目录 普通函数和箭头函数的区别loader 和 plugin 的区别webpack 怎么实现分包,为什么要分包webpack 的构建流程变量提升react 开发中遇到过什么问题什么是闭包vue 开发中遇到过什么问题vue中的 dep 和 watcher 的依赖收集是什么阶段什么是原型链react setState 是同…...
NLP高频面试题(十)——目前常见的几种大模型架构是啥样的
深入浅出:目前常见的几种大模型架构解析 随着Transformer模型的提出与发展,语言大模型迅速崛起,已经成为人工智能领域最为关注的热点之一。本文将为大家详细解析几种目前常见的大模型架构,帮助读者理解其核心差异及适用场景。 1…...
【数据结构】栈(Stack)、队列(Queue)、双端队列(Deque) —— 有码有图有真相
目录 栈和队列 1. 栈(Stack) 1.1 概念 1.2 栈的使用(原始方法) 1.3 栈的模拟实现 【小结】 2. 栈的应用场景 1、改变元素的序列 2、将递归转化为循环 3、逆波兰表达式求值 4、括号匹配 5、出栈入栈次序匹配 6、最小栈…...
windows清除电脑开机密码,可保留原本的系统和资料,不重装系统
前言 很久的一台电脑没有使用了,开机密码忘了,进不去系统 方法 1.将一个闲置u盘设置成pe盘(注意,这个操作会清空原来u盘的数据,需要在配置前将重要数据转移走,数据无价,别因为配置这个丢了重…...
NLP高频面试题(九)——大模型常见的几种解码方案
大模型常见的几种解码方案 在自然语言生成任务中,如何从模型生成的概率分布中选择合适的词汇,是影响文本质量的关键问题。常见的解码方法包括贪心搜索(Greedy Search)、束搜索(Beam Search)、随机采样&…...
「低延迟+快速集成:Amazon IVS如何重塑实时互动视频体验?」
引言:实时视频的爆发与开发痛点 随着直播电商、在线教育、云游戏的兴起,实时视频互动成为用户体验的核心。但自建视频服务面临高成本、高延迟、运维复杂等挑战。Amazon IVS(Interactive Video Service)作为亚马逊云科技推出的全托…...
JVM垃圾回收笔记02-垃圾回收器
文章目录 前言1.串行(Serial 收集器/Serial Old 收集器)Serial 收集器Serial Old 收集器相关参数-XX:UseSerialGC 2.吞吐量优先(Parallel Scavenge 收集器/Parallel Old 收集器)Parallel Scavenge 收集器Parallel Old 收集器相关参数-XX:UseParallelGC ~ -XX:UseParallelOldGC-…...
Agent Team 多智能体系统解析
引言 在人工智能技术高速发展的今天,"多智能体协作系统"(Agent Team)正成为突破效率瓶颈的关键技术。与传统的单体AI不同,这种由多个专业化智能体组成的协同网络,通过分工协作和动态调整,展现出…...
LintCode第1712题 - 和相同的二元子数组
描述 在由若干 0 和 1 组成的数组 A 中,有多少个和为 S 的非空子数组 样例 1: 输入:A [1,0,1,0,1], S 2 输出:4 解释: 如下面黑体所示,有 4 个满足题目要求的子数组: [1,0,1] [1,0,1] [1,0,1,0] [0,1,…...
网络HTTPS协议
Https HTTPS(Hypertext Transfer Protocol Secure)是 HTTP 协议的加密版本,它使用 SSL/TLS 协议来加密客户端和服务器之间的通信。具体来说: • 加密通信:在用户请求访问一个 HTTPS 网站时,客户端&#x…...