【优选算法篇】双指针的优雅舞步:C++ 算法世界的浪漫探索

news2024/10/25 5:12:05

文章目录

  • C++ 双指针详解:基础题解与思维分析
    • 前言
    • 第一章:对撞指针
      • 1.1 移动零
        • 解题思路
        • 图解分析
        • C++代码实现
        • 易错点提示
        • 代码解读
      • 1.2 复写零
        • 解题思路
        • 算法步骤
        • C++代码实现
        • 易错点提示
        • 代码复杂度
      • 1.3 盛最多水的容器
        • 1. 题目链接
        • 2. 题目描述
        • 解法一(暴力求解)
        • 解法二(对撞指针)
        • 易错点提示
        • 复杂度对比与结论
        • 小结
    • 第二章:快慢指针
      • 2.1 复写零
        • 题目链接
        • 题目描述
        • 题目分析
        • 解法(快慢指针)
        • C++代码实现
        • 代码解析
        • 易错点提示
        • 复杂度分析
    • 写在最后

C++ 双指针详解:基础题解与思维分析

💬 欢迎讨论:如有疑问或见解,欢迎在评论区留言互动。

👍 点赞、收藏与分享:如觉得这篇文章对您有帮助,请点赞、收藏并分享!
🚀 分享给更多人:欢迎分享给更多对 C++ 感兴趣的朋友,一起学习双指针的基础与进阶!


前言

双指针方法是一种常见且高效的算法技巧,常用于数组和链表问题的优化解决。在这一篇博客中,我们将通过详细的讲解和题目解析,帮助大家理解双指针的基础用法及其应用场景。


第一章:对撞指针

1.1 移动零

题目链接:283. 移动零
题目描述:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

解题思路

此题的主要思路是通过双指针法,使所有非零元素依次移动到数组前部,零元素则自动归到数组的后部。具体思路如下

  1. 初始化两个指针

    • cur:遍历整个数组。
    • dest:指向最后一个非零元素的位置,初始化为 -1。(因为不知道数组第一个元素是不是0
  2. 遍历数组

    • 如果 cur 指向非零元素,并且++dest!=cur,则将其放置在 dest + 1 的位置。
    • cur 遇到 0 时,不做任何操作,只移动 cur
  3. 结束条件

    • cur 遍历完整个数组后,dest + 1 后的所有位置自动归零,完成所需操作。
图解分析

假设数组初始为 [0, 1, 0, 3, 12]

  1. 初始状态

    • cur = 0dest = -1
    • 因为 nums[cur]0cur 右移,dest 保持不动。
  2. 步骤 1

    • cur = 1nums[cur] = 1
    • dest = -1,非零元素 1 应插入到 dest + 1 = 0 位置上。
    • 交换 nums[++dest]nums[cur],即 nums[0]nums[1],数组变为 [1, 0, 0, 3, 12]
  3. 步骤 2

    • cur = 3nums[cur] = 3
    • 此时 dest = 1
    • 3 插入 dest + 1 = 2 位置上,交换后数组变为 [1, 3, 0, 0, 12]
  4. 步骤 3

    • cur = 4nums[cur] = 12
    • 此时 dest = 2
    • 12 插入 dest + 1 = 3 位置上,交换后数组变为 [1, 3, 12, 0, 0]

步骤图解

Iterationcur Pointerdest PointerArray State
10-1[0, 1, 0, 3, 12]
210[1, 0, 0, 3, 12]
331[1, 3, 0, 0, 12]
442[1, 3, 12, 0, 0]
C++代码实现
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        for (int cur = 0, dest = -1; cur < nums.size(); cur++) {
            if (nums[cur] != 0&&++dest!= cur) {
                swap(nums[dest], nums[cur]);
            }
        }
    }
};
易错点提示
  1. 指针初始化dest-1 开始,以便于将第一个非零元素移动到 0 位置。
  2. 交换顺序:应确保 ++destcur 指向的元素交换,否则会造成非零元素错位。
  3. 理解条件判断nums[cur] 为非零时才交换,避免多余的操作。
代码解读

在代码执行中,非零元素会依次覆盖零元素的位置,最终达到将所有零移动到数组末尾的目的。此方法的时间复杂度为 O(n),空间复杂度为 O(1),即为原地操作,不占用额外空间。

这个⽅法是往后我们学习「快排算法」的时候,「数据划分」过程的重要⼀步。如果将快排算法拆解的话,这⼀段⼩代码就是实现快排算法的「核⼼步骤」。


1.2 复写零

题目链接:1089. 复写零
题目描述:给定一个固定长度的整数数组 arr,在遇到每个零时,将其右移并插入一个零,同时保持数组长度不变。

解题思路

因为数组的零元素会被重复写入两次,如果直接从前向后遍历会导致覆盖,因而最优解是使用双指针从后往前复写。算法分为两步:

  1. 找出最后一个需要复写的元素:从头到尾遍历数组,计算复写位置。
  2. 逆序复写数组:从最后一个元素开始向前,将每个零复写到目标位置,同时不覆盖后续元素。
算法步骤
  1. 初始化指针

    • cur:用来找到被复写后数组的最后一个数在原来数组的位置,初始化为0
    • dest:用于模拟复写过程,初始为 -1
  2. 寻找最后一个需要复写的元素

    • 使用 cur 遍历数组:
      • 如果 arr[cur] 非零,则 dest++
      • 如果 arr[cur] 为零,则 dest += 2
    • dest 大于或等于 n - 1(数组最后一个位置),则退出循环。
  3. 处理越界情况

    • 如果 dest == n,表示需要在最后填入一个零。
    • 此时,将 arr[n - 1] 设置为零,并调整 cur--dest -= 2 以适应边界复写。
  4. 从后向前完成复写操作

    • 使用逆序遍历从 cur 开始复写至 dest,若 arr[cur] 为零则复写两次,否则只复写一次。
C++代码实现
class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int cur = 0, dest = -1, n = arr.size();
        
        // 1. 寻找最后一个需要复写的数
        while (cur < n) {
            if (arr[cur]) dest++;        // 非零元素,dest 右移一位
            else dest += 2;              // 遇零时,dest 右移两位
            if (dest >= n - 1) break;    // 越界则退出循环
            cur++;
        }
        
        // 2. 处理边界情况,dest == n 时需在末尾填零
        if (dest == n) {
            arr[n - 1] = 0;
            cur--;
            dest -= 2;
        }
        
        // 3. 从后向前复写元素
        while (cur >= 0) {
            if (arr[cur]) {
                arr[dest--] = arr[cur];  // 非零元素,复写到 dest 位置
            } else {
                arr[dest--] = 0;         // 遇到零时,连续写两次
                arr[dest--] = 0;
            }
            cur--;
        }
    }
};

假设数组为 arr = [1, 0, 2, 3, 0, 4, 5, 0]

步骤 1:找到最后一个需要复写的元素

  • 初始化 cur = 0dest = -1n = 8
  • 遍历数组,遇到零元素时 dest 向后移动两位,遇到非零元素时 dest 向后移动一位。目标是找到最后一个需要复写的元素位置 cur
int cur = 0, dest = -1, n = arr.size();
while (cur < n) {
    if (arr[cur]) dest++;   // 非零元素
    else dest += 2;         // 零元素,移动两位
    if (dest >= n - 1) break;
    cur++;
}

遍历示例:

  • cur = 0arr[0] = 1dest++,所以 dest = 0
  • cur = 1arr[1] = 0dest += 2,所以 dest = 2
  • 依此类推,最终 cur = 5dest = 7,在此位置结束循环。

步骤 2:逆序填充

在此时,cur5dest7。从这两个位置开始逆序复写,以避免前面的零覆盖其他元素:

IterationcurdestArray State
Start57[1, 0, 2, 3, 0, 4, 5, 0]
146[1, 0, 2, 3, 0, 4, 5, 4]
233[1, 0, 2, 3, 0, 0, 0, 4]
412[1, 0, 2, 2, 3, 0, 0, 0]
512[1, 0, 0, 2, 3, 0, 0, 0]
Final01[1, 0, 0, 2, 3, 0, 0, 4]

具体操作解释:

  1. 开始cur = 5dest = 7,将 arr[5] 的值 4 复制到 arr[7]
  2. 遇到零cur = 4,在 arr[6]arr[5] 连续填入 0
  3. 复写非零元素cur = 3,将 arr[3] 的值 3 复制到 arr[4]
  4. 继续填充非零和零元素cur = 2cur = 1 分别填入 2 和两个 0
  5. 最终结果:通过逆序复写确保零元素不覆盖其他元素,得到 [1, 0, 0, 2, 3, 0, 0, 4]
易错点提示
  1. 目标位置初始化dest-1 开始,以保证cur准确定位复写后数组最后一个元素在原来数组的位置。
  2. 越界处理:若 dest 超出数组边界时,最后一个位置设为零,并调整 curdest
  3. 逆序复写逻辑:确保零元素复写两次、非零复写一次,保证整个过程的准确性。
代码复杂度
  • 时间复杂度:O(n),只需遍历两次。
  • 空间复杂度:O(1),仅使用少量额外变量。

1.3 盛最多水的容器

1. 题目链接

11. 盛最多水的容器

2. 题目描述

给定一个长度为 n 的整数数组 height,有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i])
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。

在这里插入图片描述

说明:你不能倾斜容器。

示例 1

  • 输入:[1,8,6,2,5,4,8,3,7]
  • 输出:49
  • 解释:数组中的垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在这个情况下,能够容纳水(表示为蓝色部分)的最大值是 49
解法一(暴力求解)

算法思路

  • 枚举出所有可能构成的容器,找出其中容积最大的值。
  • 容器容积的计算方式:
    • 设指针 ij 分别指向容器的最左端和最右端,此时容器的宽度为 j - i
    • 由于容器的高度由两条边中较短的决定,因此容积的公式为:
      v = (j - i) * min(height[i], height[j])
      
  • 遍历所有可能的组合,计算每次的容积,并找出最大值。

代码实现

class Solution {
public:
    int maxArea(vector<int>& height) {
        int n = height.size();
        int ret = 0;
        // 两层 for 循环枚举出所有可能出现的情况
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                // 计算容积,找出最大的那一个
                ret = max(ret, min(height[i], height[j]) * (j - i));
            }
        }
        return ret;
    }
};

复杂度分析

  • 时间复杂度O(n^2)。需要遍历所有的可能组合,计算每个组合的容积,因此时间复杂度为平方级别。
  • 空间复杂度O(1)。只使用了常数个变量存储结果和中间值。

缺点

  • 该算法对大数据集会产生性能问题,会超时。因此需要寻找更高效的解法
解法二(对撞指针)

算法思路

  • 使用两个指针 leftright 分别指向容器的左右两个端点。
  • 容器的初始状态为 left 在最左侧,right 在最右侧。
  • 容积公式
    v = (right - left) * min(height[right], height[left])
    
  • 通过移动两个指针来寻找最大的容积:
    • 如果左边界小于右边界,则移动左边界 left++。因为固定左边界且继续移动右边界,只会使得容器宽度减小,而高度仍然由左边的短板决定,因此容积只能减小。
    • 同理,如果右边界小于左边界,则移动右边界 right--,以尝试找到更高的边界,从而可能获得更大的容积。
  • 重复以上过程,直到 leftright 相遇,整个过程中不断更新最大容积的值。

代码实现

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;
    }
};

复杂度分析

  • 时间复杂度O(n)。只需要遍历整个数组一次,两个指针分别从头和尾相向而行。
  • 空间复杂度O(1)。只使用了常数个变量存储结果和指针位置。

核心思想与证明

  • 双指针法的有效性:通过每次移动较短边界的方式,可以确保不会遗漏任何可能的最大容积的组合。因为容器的高度由两侧较短的一边决定,通过移动较短的那一边,我们尝试找到更高的边界,保持或增加容积。
  • 为什么移动短板?
    • 当左右边界不相等时,容器的高度取决于较短的一边。如果固定较短边界而移动较长边界,容器的高度不会增加,宽度还会减小,因此容积一定会减少。
    • 而如果移动较短的边,可能找到一个更高的边,从而在宽度减少的情况下保持或增加高度,从而有可能获得更大的容积。
易错点提示
  1. 指针移动逻辑

    • 在指针移动过程中,不是随机移动,而是根据较短边界的高度决定移动哪个指针。目的是通过增加高度的可能性来找到更大的容积。
  2. 边界条件的处理

    • 初始状态 left = 0right = height.size() - 1,要注意判断数组的长度不能为零,否则无法构成容器。
复杂度对比与结论
  • 暴力求解法:时间复杂度为 O(n^2),对于较大的输入会导致超时,适合小规模数据。
  • 对撞指针法:时间复杂度为 O(n),只需线性遍历,适合大规模输入,能够有效解决性能问题。
小结
  • 这道题考察了如何通过合理的指针移动来减少不必要的计算,双指针法的精髓在于每次有目的地舍弃一些不可能产生最大值的组合,从而将时间复杂度降至线性。
  • 在实际解题时,双指针法是一种非常高效的解法,特别适用于涉及到对区间或边界的遍历优化问题。

通过这两种方法的对比,我们可以看到,暴力法虽然简单,但在性能上存在很大的不足,而通过双指针策略,我们能够有效地减少重复计算,找到问题的最优解。

第二章:快慢指针


2.1 复写零

题目链接

202. 快乐数

题目描述

编写一个算法来判断一个数 n 是不是快乐数。

快乐数定义

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程,直到这个数变为 1,或者进入无限循环但始终无法变为 1
  • 如果这个过程结果为 1,那么这个数就是快乐数。
  • 如果 n 是快乐数就返回 true;否则返回 false

示例 1

  • 输入:n = 19
  • 输出:true
  • 解释:
    • 19 -> 1^2 + 9^2 = 82
    • 82 -> 8^2 + 2^2 = 68
    • 68 -> 6^2 + 8^2 = 100
    • 100 -> 1^2 + 0^2 + 0^2 = 1

示例 2

  • 输入:n = 2
  • 输出:false
  • 解释:
    • 2 -> 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16
    • 出现了重复的数字,因此进入了无限循环,不是快乐数。
题目分析

为了方便叙述,将“对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和”这一操作记为 x 操作

题目告诉我们,当我们不断重复 x 操作 时,计算一定会进入“死循环”,而“死循环”的方式有两种:

  • 情况一:不断循环到 1,即 1 -> 1 -> 1 -> 1...,这是“快乐数”。
  • 情况二:在某个历史数值中循环,始终变不到 1

由于上述两种情况只会出现一种,因此,只要我们能确定循环是在“情况一”还是“情况二”,就能判断该数是否是快乐数。

简单证明

  • 变化值范围:经过一次变化后的最大值为 9^2 * 10 = 810(即最大的情况是 9999999999(实际上这道题没有这么大),由鸽巢原理,这个值最终的范围在 [1, 810] 之间)。
  • 循环保证:根据“鸽巢原理”,一个数变化 811 次之后,必然会形成一个循环。
  • 因此,变化的过程最终会进入一个圈里,可以使用快慢指针来判断是否进入循环。
解法(快慢指针)

算法思路
根据题目分析,我们可以知道,当重复执行 x 操作 时,数值会陷入某种“循环”之中。而快慢指针有一个特性,就是在一个环中,快指针总是会追上慢指针,也就是说它们总会相遇在某个位置上。

  • 如果相遇的位置是 1,则这个数是快乐数;
  • 如果相遇的位置不是 1,则这个数不是快乐数。

补充知识:如何求一个数 n 每个位置上的数字的平方和:

  • 把数 n 每一位的数字提取出来,使用以下步骤:
    • 提取个位:int t = n % 10
    • 去掉个位:n /= 10
    • 重复上面的步骤,直到 n 的值为 0
  • 在提取每一位时,用一个变量 sum 记录平方和:sum += t * t
C++代码实现

以下是 C++ 的代码实现,使用快慢指针来解决该问题:

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;  // 判断相遇点是否为 1
    }
};
代码解析
  • bitSum 函数
    • 用于求一个数 n 的每位数字平方和。
    • 通过循环不断提取个位,计算平方和,直到 n0
  • isHappy 函数
    • 初始化两个指针 slowfast,分别为 nbitSum(n)
    • 使用 快慢指针 的方式来进行循环,slow 每次只走一步,而 fast 每次走两步。
    • 如果 slowfast 相遇,退出循环。
    • 最后判断是否相遇在 1 上,若是则返回 true,表示为快乐数,否则返回 false
易错点提示
  1. 快慢指针相遇判断

    • 需要注意的是,当 slowfast 相遇时,如果该值为 1,则为快乐数;如果不是 1,则表明进入了其他循环。
  2. 平方和计算函数的实现

    • 在实现 bitSum 函数时,需要注意提取个位后立即对其平方,并累加到总和中,最后在循环结束后返回结果。
复杂度分析
  • 时间复杂度O(log n)。在快慢指针法中,求平方和的时间复杂度为对数级。
  • 空间复杂度O(1)。没有使用额外的数据结构,只使用了固定数量的变量。

写在最后

在这篇文章中,我们从基础开始,深入探讨了双指针方法在解决常见数组问题中的魔力。双指针法的魅力在于其精妙的指针移动方式,使得看似复杂的问题变得简单而高效。通过实例与代码实现,我们详细讲解了对撞指针和双指针的使用,帮助大家掌握这一关键的算法技巧。

在这四道经典题目中,我们一步步剖析了双指针在实际问题中的应用。从“移动零”到“复写零”,再到最大水容器的计算,我们不仅关注解题思路的解析,还揭示了双指针法在优化时间复杂度上的巧妙之处。

接下来,我们将深入“快慢指针”的世界,探讨它如何用于解决环形问题,以及如何帮助我们识别复杂链表结构中的循环。希望你继续关注,和我们一起开启算法探索的新篇章。

以上就是关于【C++篇】虚境探微:多态的流动诗篇,解锁动态的艺术密码的内容啦,各位大佬有什么问题欢迎在评论区指正,或者私信我也是可以的啦,您的支持是我创作的最大动力!❤️

在这里插入图片描述

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

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

相关文章

链表(4)_合并K个升序链表_面试题

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 链表(4)_合并K个升序链表_面试题 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录…

第十五届蓝桥杯C++B组省赛

文章目录 1.握手问题解题思路1&#xff08;组合数学&#xff09;解题思路2&#xff08;暴力枚举&#xff09; 2.小球反弹做题思路 3.好数算法思路&#xff08;暴力解法&#xff09;---不会超时 4.R格式算法思路 5.宝石组合算法思路---唯一分解定理 6.数字接龙算法思路----DFS 7…

【Oracle数据库进阶】001.SQL基础查询_查询语句

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…

Egg考古系列-EggCore的生命周期

关于EGG egg框架的第一个版本还是2017-03-21&#xff0c;距今已有7年了。虽然最近几年没有什么更新&#xff0c;但它在国内的使用还是挺多的&#xff0c;mvc的分层模式也很受大家喜欢。虽然声称是面向企业级、中大型项目场景的框架&#xff0c;但这种约定式在大型项目中其实也很…

高校学科竞赛管理:SpringBoot实现的高效策略

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

【M2-Mixer】核心方法解读

abstract&#xff1a; 在本文中&#xff0c;我们提出了M2-Mixer&#xff0c;这是一种基于MLPMixer的结构&#xff0c;具有多头损失&#xff0c;用于多模态分类。它比基于卷积、循环或神经结构搜索的基线模型具有更好的性能&#xff0c;其主要优势是概念和计算简单。所提出的多…

【电子电力】LCL滤波器设计,包括电流控制调谐

摘要 LCL 滤波器是电力电子领域中广泛应用于并网逆变器的滤波器之一&#xff0c;其主要功能是减少高频开关的谐波&#xff0c;确保输出电流的质量。本文设计并实现了基于 MATLAB 的 LCL 滤波器模型&#xff0c;结合电流控制器和调谐技术&#xff0c;验证了其在谐波抑制方面的效…

从RNN讲起(RNN、LSTM、GRU、BiGRU)——序列数据处理网络

文章目录 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09;1. 什么是RNN&#xff1f;2. 经典RNN的结构3. RNN的主要特点4. RNN存在问题——长期依赖&#xff08;Long-TermDependencies&#xff09;问题 LSTM&#xff08;Long Short-Term Memory&a…

PostgreSQL学习笔记七:常规SQL操作

PostgreSQL 支持标准的 SQL 语句&#xff0c;同时也扩展了一些特有的功能。以下是一些常规的 SQL 语句示例&#xff0c;这些示例涵盖了数据定义、数据操作和数据查询的基本操作&#xff1a; 数据定义语言 (DDL 创建数据库&#xff1a; CREATE DATABASE mydatabase;创建表&#…

stm32单片机个人学习笔记9(TIM输入捕获)

前言 本篇文章属于stm32单片机&#xff08;以下简称单片机&#xff09;的学习笔记&#xff0c;来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记&#xff0c;只能做参考&#xff0c;细节方面建议观看视频&#xff0c;肯定受益匪浅。 STM32入门教程-2023版 细…

AWD入门

一、简介 AWD(Attack With Defense&#xff0c;攻防兼备)模式。你需要在一场比赛里要扮演攻击方和防守方&#xff0c;攻者得分&#xff0c;失守者会被扣分。也就是说攻击别人的靶机可以获取 Flag 分数时&#xff0c;别人会被扣分&#xff0c;同时你也要保护自己的主机不被别人…

Docker 教程四 (Docker 镜像加速)

Docker 镜像加速 国内从 DockerHub 拉取镜像有时会遇到困难&#xff0c;此时可以配置镜像加速器。 目前国内 Docker 镜像源出现了一些问题&#xff0c;基本不能用了&#xff0c;后期能用我再更新下。* Docker 官方和国内很多云服务商都提供了国内加速器服务&#xff0c;例如…

Python网络爬虫入门指南

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

MPA-SVM多变量回归预测|海洋捕食者优化算法-支持向量机|Matalb

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、算法介绍&#xff1a; 四、完整程序下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matlab平台编译&am…

2024年网络安全进阶学习路径-2024年进阶学习指南

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 前言 什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、…

KDD 2024论文分享┆用于序列推荐的数据集再生

论文简介 本推文介绍了2024 KDD的最佳学生论文《Dataset Regeneration for Sequential Recommendation》。该论文提出了一种基于数据中心化范式的新框架&#xff0c;称为DR4SR&#xff0c;该框架通过模型无关的数据再生机制&#xff0c;能够生成具有出色跨架构泛化能力的理想训…

git(版本回退,分支管理,vscode集成git)

一、安装与简单命令 1.官网 https://git-scm.com/downloads 2.查看版本号git --version 3.设置用户签名&#xff08;用户名和邮箱&#xff09; 用来标识用户&#xff0c;以区分不同的开发人员 git config --global user.name "Your Name" git config --global u…

2024年最新算法:青蒿素优化算法(Artemisinin Optimization Algorithm, AOA)原理介绍

青蒿素优化算法&#xff08;Artemisinin Optimization Algorithm, AOA&#xff09;是2024年提出的一种受青蒿素抗疟疾特性启发的元启发式优化算法。青蒿素是一种从中草药青蒿中提取的化合物&#xff0c;因其在治疗疟疾方面的显著效果而闻名。AOA算法的设计者将青蒿素的这一特性…

【机器学习】深入浅出讲解贝叶斯分类算法

0. 前言 1.贝叶斯分类器介绍 贝叶斯分类是一类分类算法的总称&#xff0c;这类算法均以贝叶斯定理为基础&#xff0c;故统称为贝叶斯分类。而朴素贝叶斯&#xff08;Naive Bayes&#xff09;分类是贝叶斯分类中最简单&#xff0c;也是常见的一种分类方法。 一些很常见的分类…

动态规划最大子段和讲解和【题解】——最大子段和

动态规划最大子段和讲解和【题解】——最大子段和 1.详细讲解最大子段和题目描述输入格式输出格式输入输出样例输入 #1输出 #1 提示样例 1 解释数据规模与约定 1.1.思路解析1.2.AC代码 2.优化3.别言 1.详细讲解 最大子段和 题目描述 给出一个长度为 n n n 的序列 a a a&am…