《双指针算法指南: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)。

我的笔记:

  1. dest 初始化为 -1,巧妙处理初始边界

  2. 交换操作后只需 dest++,无需重复检查已处理区域

  3. 对比老师的代码,发现 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--;}}}
};

我的思路:

  1. 模拟填充:先用快慢指针找到最后一个有效元素的位置
  2. 边界修正:若模拟填充时 dest 越界,需手动处理末尾零
  3. 逆向复写:从后往前填充,遇到零则复写两次

我的笔记:

  1. 注意边界情况
  2. dest 的移动规则:遇到非零+1,遇到零+2
  3. 逆向复写时,cur 指针的起始位置需通过模拟填充确定
  4. 边界条件 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;}};

我的思路:

  • 定义 fastslow 指针,fast 每次计算两次平方和,slow 一次
  • 若两指针相遇且值为1,则是快乐数;否则存在非1循环

我的笔记:

  1. 要学会老师取一个整数的每一位数的方法

  2. 简化代码

  3. 当提到无限循环的时候就要想到能不能用快慢双指针的方法解决问题,就像链表成环问题一样

  4. 平方和函数可用取余法优化:while(n) { t = n%10; sum += t*t; n /=10; }

  5. 快慢指针相遇后只需判断是否为1,无需继续计算

  6. 时间复杂度从 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;}
};

我的思路:

从两端往中间靠拢的过程中,长度一直在减少,因此要想找到比现在还大的容积只有当高度比现在指针指向的高度还要高的情况才有可能出现,因此才有了上面的判断条件

我的笔记:

  1. 使用函数max() 和min()
  2. 贪心思想的典型应用
  3. 即使移动后高度可能降低,但宽度减少的损失已被提前计算
  4. 时间复杂度 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;}
};

我的思路:

  1. 排序数组,逆序枚举最大边 nums[i]
  2. 双指针 left=0right=i-1 搜索满足 nums[left] + nums[right] > nums[i] 的组合
  3. 若满足条件,则 right-left 个组合均有效

我的笔记:

  1. 排序算法,已经使用模版了,所以只需要使用模版中的排序算法就行了
  2. 排序时间复杂度 O(nlogn) 主导整体效率
  3. 双指针将内层循环从 O(n²) 优化到 O(n)
  4. 关键代码逻辑: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};}
};

我的思路:

我的笔记:

  1. 这里使用了一个大括号的隐式类型转换
三数之和

题⽬链接:

三数之和

要点:

  • 去重是关键:固定数、左指针、右指针均需跳过重复值
  • 排序后使用双指针将时间复杂度从 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;}
};

我的思路:

要点:

  1. 算法思:双指针思想

    先排序

    然后固定⼀个数 a

    在这个数后⾯的区间内,使⽤「双指针算法」快速找到两个数之和等于 -a 即可 (这一条只要满足题意都可以)

  2. 注意:

    找到⼀个结果之后, left 和 right 指针要「跳过重复」的元素;

    使⽤完⼀次双指针算法之后,固定的 a 也要「跳过重复」的元素

    越界判断

  3. 固定第一个数 nums[i],转化为两数之和问题

  4. 双指针 left=i+1right=n-1 搜索 target = -nums[i]

  5. 去重操作需在找到解后立即执行

我的笔记:

  1. 我提交的代码是有一些无法通过的,其实就是边界问题没有处理好,如:

    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–;是否越界的情况

  2. 注意去重与越界访问问题,以后写代码都要记得考虑一下这个问题

  3. 去重代码模板:

    while (i < n && nums[i] == nums[i-1]) i++;  // 外层去重  
    while (left < right && nums[left] == nums[left-1]) left++;  // 内层去重  
    
  4. 边界检查 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;}
};

我的思路:

  1. 双重循环固定前两个数 nums[i]nums[j]
  2. 双指针 left=j+1right=n-1 搜索剩余两数
    1. 每层循环均需去重

我的笔记:

  1. 去重:与前面的三数之和是一样的,去重时要考虑边界问题
  2. 边界问题:不去重的时候也要注意边界问题
  3. 这个题目在计算时会有数据溢出的风险,因此代码中用到了long long,此时在计算时算式的右边第一个变量也要强转成long long 类型
  4. 溢出处理:long long aim = (long long)target - nums[i] - nums[j];
  5. 去重逻辑与三数之和一致,需在每层循环后跳过重复值
  6. 时间复杂度 O(n³),但实际运行效率较高

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PDF文件转Markdown,基于开源项目marker

​ 首先我们来问下deepseek 为啥要选marker呢 基于深度学习&#xff0c;一看就逼格拉满。搞科研必备&#xff0c;效果应该不会太差。跟其他的阿猫阿狗工具没法比。 看下官网 https://github.com/VikParuchuri/marker ​ 一看头像是个印度佬&#xff0c;自吹——又快又好。…

【深度学习与大模型基础】第6章-对角矩阵,对称矩阵,正交矩阵

一、对角矩阵 对角矩阵&#xff08;Diagonal Matrix&#xff09;是一种特殊的方阵&#xff0c;其非对角线上的元素均为零&#xff0c;只有对角线上的元素可能非零。具体来说&#xff0c;对于一个 nn的矩阵 A[]&#xff0c;如果满足 则 AA 称为对角矩阵。对角矩阵通常表示为&am…

C语言 数据结构【动态顺序表】详解

引言 详细介绍了顺序表中各个接口的实现&#xff0c;一定要亲自动手敲一遍&#xff0c;要能想象出具体的图像 第一次敲可能不能完全靠自己敲出来&#xff08;很正常&#xff09;&#xff0c;过一段时间可以根据顺序表的原理敲第二遍 孰能生巧 一、线性表 在介绍顺序表之前先…

人脸表情识别系统分享(基于深度学习+OpenCV+PyQt5)

最近终于把毕业大论文忙完了&#xff0c;众所周知硕士大论文需要有三个工作点&#xff0c;表情识别领域的第三个工作点一般是做一个表情识别系统出来&#xff0c;如下图所示。 这里分享一下这个表情识别系统&#xff1a; 采用 深度学习OpenCVPyQt5 构建&#xff0c;主要功能包…

集成学习(下):Stacking集成方法

一、Stacking的元学习革命 1.1 概念 Stacking&#xff08;堆叠法&#xff09; 是一种集成学习技术&#xff0c;通过组合多个基学习器&#xff08;base learner&#xff09;的预测结果&#xff0c;并利用一个元模型&#xff08;meta-model&#xff09;进行二次训练&#xff0c…

tcping 命令的使用,ping IP 和端口

1. ‌Windows系统安装‌ ‌下载tcping工具‌&#xff1a;根据系统位数&#xff08;32位或64位&#xff09;下载对应的tcping.exe文件。‌安装步骤‌&#xff1a; 将下载的tcping.exe文件复制到C:\Windows\System32目录下。如果下载的是64位版本&#xff0c;需将文件名改为tcpi…

浅谈跨平台框架的演变(H5混合开发->RN->Flutter)

引言 这里分为四个阶段&#xff1a; 第一阶段 &#xff1a; 原生开发 第二阶段 &#xff1a; H5混合开发 第三阶段&#xff1a; 跨平台RN 第四阶段&#xff1a; 跨平台Flutter 正文 第一阶段&#xff1a; 原生开发 开发成本比较大 &#xff1a; 需要Android 和ios 开发两…

《TCP/IP网络编程》学习笔记 | Chapter 20:Windows 中的线程同步

《TCP/IP网络编程》学习笔记 | Chapter 20&#xff1a;Windows 中的线程同步 《TCP/IP网络编程》学习笔记 | Chapter 20&#xff1a;Windows 中的线程同步用户模式和内核模式用户模式同步内核模式同步 基于 CRITICAL_SECTION 的同步内核模式的同步方法基于互斥量对象的同步基于…

力扣45.跳跃游戏

45. 跳跃游戏 II - 力扣&#xff08;LeetCode&#xff09; 代码区&#xff1a; #include<vector> class Solution {public:int jump(vector<int>& nums) {int ans[10005] ;memset(ans,1e4,sizeof(ans));ans[0]0;for(int i0;i<nums.size();i){for(int j1;j…

深入理解 Collections.emptyList():优雅处理空列表的利器!!!

&#x1f680; 深入理解 Collections.emptyList()&#xff1a;优雅处理空列表的利器&#xff01;&#x1f527; 大家好&#xff01;&#x1f44b; 今天我们来聊聊 Java 中一个非常实用但容易被忽视的小工具——Collections.emptyList()。&#x1f389; 如果你经常需要返回一个…

SpringBoot教程(十四) SpringBoot之集成Redis

SpringBoot教程&#xff08;十四&#xff09; | SpringBoot之集成Redis 一、Redis集成简介二、集成步骤 2.1 添加依赖2.2 添加配置2.3 项目中使用之简单使用 &#xff08;举例讲解&#xff09;2.4 项目中使用之工具类封装 &#xff08;正式用这个&#xff09;2.5 序列化 &…

VC6.0图文安装教程

VC6.0图文安装教程 ​ 1、首先&#xff0c;右击安装包&#xff0c;以管理员身份运行 2、点击下一步 ​​​​ 3、点击下一步 4、选择安装路径&#xff0c;点击下一步 5、点击下一步 6、点击安装 7、安装ing 8、点击完成 至此&#xff0c;安装完成&#xff01;

用户说 | 零基础用通义灵码 AI 程序员开发个人笔记网站

作者&#xff1a;宋镇江&#xff0c;安阳幼儿师范高等专科学校数字媒体技术专业教师 通义灵码是一款基于通义大模型的智能编码辅助工具&#xff0c;支持自然语言生成代码、单元测试生成、代码注释生成等功能&#xff0c;兼容多种主流IDE和编程语言。对于零基础用户&#xff0c…

试验一 mybatis 入门操作

试验一 mybatis 入门操作 一 实验目的 1.掌握mybatis基础操作&#xff0c;包括如何在maven工程中引入依赖&#xff0c;创建mapper文件&#xff0c;核心配置文件&#xff0c;映射文件&#xff0c;并测试对数据库表基本的的CRUD操作&#xff1b; 2.掌握核心配置文件中几个重要标…

使用Gitee Go流水线部署个人项目到服务器指南

使用Gitee Go流水线部署个人项目到服务器指南 前言&#xff01;&#xff01;&#xff01; 本文解决的问题&#xff1a; 你有一台ECS服务器&#xff0c;你在上面部署了一个Java服务也就是一个jar&#xff0c;你觉着你每次手动本地打包&#xff0c;上传&#xff0c;在通过命令去…

LCCI ESG 中英联合认证国际分析师适合的岗位

LCCI ESG中英联合认证国际分析师领域热门岗位大揭秘&#xff01;&#x1f30d; 大家好&#xff01;今天我们来探讨LCCI ESG中英联合认证国际分析师领域的热门岗位&#xff0c;看看是否有适合你的选择。 1️⃣ LCCI ESG中英联合认证国际分析师报告专员&#xff1a;主要负责编制…

Compose 实践与探索十五 —— 自定义触摸

1、自定义触摸与一维滑动监测 之前我们在讲 Modifier 时讲过如下与手势检测相关的 Modifier&#xff1a; Modifier.clickable { } Modifier.combinedClickable { } Modifier.pointerInput {detectTapGestures { } }这里对以上内容就不再赘述了&#xff0c;直接去讲解更复杂的…

【Linux】Makefile秘籍

> &#x1f343; 本系列为Linux的内容&#xff0c;如果感兴趣&#xff0c;欢迎订阅&#x1f6a9; > &#x1f38a;个人主页:【小编的个人主页】 >小编将在这里分享学习Linux的心路历程✨和知识分享&#x1f50d; >如果本篇文章有问题&#xff0c;还请多多包涵&a…

LDAP从入门到实战:环境部署与配置指南(上)

#作者&#xff1a;朱雷 文章目录 一、LDAP 简介1.1. 什么是目录服务1.2. 什么是 LDAP1.3. LDAP的基本模型 二、Ldap环境部署2.1.下载软件包2.2.安装软件2.3.编辑配置文件2.4.启动服务 一、LDAP 简介 1.1. 什么是目录服务 目录是专门为搜索和浏览而设计的专用数据库&#xff…

《C++智能指针:建议使用 make_shared 代替 shared_ptr》

《C 智能指针&#xff1a;长达数十年的血泪史&#xff0c;一步步征服内存泄漏》-CSDN博客 shared_ptr<int> sp1(new int(10)); 这句代码实际存在两个内存开辟&#xff0c;一是开辟我们要托管的内存资源 &#xff0c;二是开辟引用计数的资源&#xff0c;引用技术也是new出…