代码随想录算法训练营day7 | 454.四数相加II、383.赎金信、15.三数之和、18.四数之和

news2024/11/14 4:06:59

文章目录

    • 454.四数相加II
      • 思路
    • 383.赎金信
      • 思路
    • 15.三数之和
      • 思路
      • 剪枝+去重
    • 18.四数之和
      • 思路
      • 剪枝+去重
      • 复习:C++中的类型转换方法
    • 总结

今天是哈希表专题的第二天

废话不多说,直接上题目

454.四数相加II

建议:本题是 使用map 巧妙解决的问题,好好体会一下 哈希法 如何提高程序执行效率,降低时间复杂度,当然使用哈希法 会提高空间复杂度,但一般来说我们都是舍空间 换时间, 工业开发也是这样。

题目链接:454. 四数相加 II - 力扣(LeetCode)

题目说明:本题需要考虑四个数组如何组合,加和为0。只需要计算有多少种组合,而不需要写出具体的组合方式。同时,本题认为:对于数组中位置不同的元素a、b,即使a与b的值相同(a == b),a、b也被视为不同的元素,所以我们不需要“去重”,比如四个数组的元素都是n个0,则认为有不只一个组合,每个组合都是0000、0000···,区别在于不同组合中的0取自数组的不同位置(比如第一个组合的第一个0取自nums1[0],第二个组合的第一个0取自nums1[1]),这是本题与后面的一道题目 18.四数之和 的不同之处

思路

这道题目解法很巧妙,但是有迹可循:前一篇文章day6中的最后一道题 1.两数之和 思路与本题相似,我们可以参照 两数之和 中的思路

两数之和中,需要在同一个数组中找到相匹配(a+b == target)的元素a、b的下标,思路是:遍历一遍整个数组,同时创建一个map映射作为哈希表记录遍历过的元素的值和下标。每遍历到一个元素a,就从哈希表中查找是否有相匹配的元素b,即auto it = map.find(target-a)。若b在哈希表中,则返回a和b的下标,即return {i, it->second},遍历结束;否则,将元素a的 值和下标 作为键值对,添加到map中,继续遍历

我们把这个思路应用到这道题中:首先遍历数组A、B,使用map记录数组A、B的和(a+b),然后双层for循环,求数组C、D的和(c+d),在 map中查找是否存在相匹配的a+b(相匹配指的是a+b+c+d == 0),即auto it = map.find(0-(c+d))。这是一个大概的思路,我们接下来讨论一些细节问题

  • 为什么不用数组或集合作为哈希表

    数组作为哈希表乍一看可以,但是本题中a+b的值是没有大小限制的,这就戳到了数组的痛点:键的大小必须有大小限制,因此不能使用数组作为哈希表

    集合中只能存储键a+b的值,无法存储a+b出现次数的信息,因此也不能使用集合作为哈希表

  • map的键值是什么

    题目需要求出a+b+c+d == 0的组合数量,而不用列出具体的组合的方式。如果0-(c+d)在map中找到了,即it != map.end(),那么it->second应该是a+b+c+d == 0的组合数量,这个组合的数量 等于 a+b=0-(c+d)出现的次数,用下面的例子解释:

    image-20240724153341415

    若当前c=-1,d=2,那么要从map中找到a+b = 0-(c+d) = -1。map中,a+b = -1共出现了一次:a=1,b=-2,所以当c=-1,d=2时,a+b+c+d == 0这样的组合只有一个,就是a+b=-1出现的次数

    通过上述分析可知,我们使用0-(c+d)在map中寻找,需要获得a+b=0-(c+d)的出现次数,因此map的键值对为**<a+b的值val, a+b=val的出现次数>**

  • 能不能只用A构建map,然后再遍历B、C、D三个数组寻找0-(b+c+d)

    可以,但是时间复杂度是O(n3),而我们两两遍历,时间复杂度是O(n2),因此还是用A、B构建map,然后再遍历C、D更加合适

  • 整体思路

    首先遍历数组A、B,使用map记录数组A、B的和(a+b),key存放a和b两数之和,value存放a和b两数之和出现的次数。然后遍历数组C、D,求数组C、D的和(c+d),在map中查找是否存在相匹配的a+b(相匹配指的是a+b+c+d == 0),即auto it = map.find(0-(c+d))。如果找到了,即it != map.end(),那么count += it->second(count加上key对应的value),统计这个组合的数量;否则不做处理。遍历完C和D后返回count,这个count就是四个数组中a+b+c+d == 0的组合数量

代码实现

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        // 思路就是先进行两个数组A、B的加法,得到一个哈希表,key为a+b的值,value为这个值出现的次数
        // 然后双层for循环,先对C、D做加法,和为c+d,然后再哈希表中查找0-(c+d),如果找到了,则这个键对应的值是a+b+c+d=0组合的出现次数
        std::unordered_map<int, int> map;
        for(int a : nums1)
        {
            for(int b : nums2)
            {
                map[a+b]++;
            }
        }
        int count = 0;
        for(int c : nums3)
        {
            for(int d : nums4)
            {
                auto it = map.find(0-(c+d));
                if( it != map.end())
                {
                    count += it->second; 
                }
            }
        }
        return count;
    }
};
  • 时间复杂度: O(n2)
  • 空间复杂度: O(n2),最坏情况下A和B的值各不相同,相加产生的数字个数为 n2

383.赎金信

本题 和 242.有效的字母异位词 是一个思路 ,算是拓展题

题目链接:383. 赎金信 - 力扣(LeetCode)

思路

本题中两个字符串都是用小写字母组成,key的大小是有限制的,所以我们可以使用数组实现哈希表。数组的key是 字符串magazine中的各个字符-‘a’,value是 字符串magazine中的各个字符出现的次数

由于map需要维护红黑树或者哈希表,而且还要做哈希函数,所以很费时,而且map的空间消耗要比数组的大,所以能用数组就不map,使用数组更加简单有效

代码实现

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        vector<int> record(26, 0);
        if(ransomNote.size() > magazine.size())
        {
            return false;
        }
        // 首先统计magazine中各个字出现的次数
        for(char c : magazine)
        {
            record[c-'a']++;
        }
        // 然后检查这些字符是否能组成ransomNote
        for(char c : ransomNote)
        {
            if(--record[c-'a'] < 0) // 注意是--record,不是record--,要先减再判断
            {
                return false;
            }
        }
        return true;
    }
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

15.三数之和

建议:本题虽然和 两数之和 很像,也能用哈希法,但用哈希法会很麻烦,双指针法才是正解,可以先看视频理解一下 双指针法的思路。

题目链接:15. 三数之和 - 力扣(LeetCode)

这道题的测试用例有点癫😧

思路

本题的难点在于找到不重复的三元组,这就需要去重,本题与454.四数之和II是不同的

哈希法查找元素是没有顺序的,去重的时候会很麻烦,本题使用排序+双指针法

排序+双指针法

  • 初始化首先将数组排序,然后有一层for循环遍历数组,下标i从0的开始,同时定义一个下标left定义在i+1的位置上,定义下标right在数组末尾的位置上

  • 寻找过程:要在数组中找到三元组{a, b, c}使得a+b+c == 0,这里a = nums[i],b=nums[left],c=nums[right]

    接下来如何移动left 和 right 呢?有三种情况:

    • 如果a + b + c > 0,则说明nums[right]太大了,right–
    • 如果a + b + c < 0,则说明nums[left]太小了,left++
    • 如果a + b + c == 0,则找到了一个三元组{a, b, c},我们将它用一个二维数组存放起来,然后左右指针同时紧缩,即依次做right-- 和 left++
  • 结束本次查找,遍历下一个元素:当left与right相遇时,我们结束left和right的移动,然后i++,移动到下一个元素,继续进行上述步骤,直至数组遍历完了

注意:while循环终止条件是right > left还是right >= left呢?对于这样的边界条件,我们可以设身处地的想一想,当right == left时,nums[left]nums[right]是同一个元素,此时找到的a+b+c == 0的三元组没有意义,因此循环条件是right > left

执行过程如图所示:

15.三数之和

剪枝+去重

  1. 剪枝:排除后续元素全为正的数组:每次遍历都需要先判断nums[i]是否大于0。如果nums[i] > 0,则说明数组的第i位后的所有元素都是正的,不可能出现a+b+c == 0的情况

  2. 去重:对a去重,判断nums[i] == nums[i-1],若成立,则continue

    比如有数组nums = {-1, -1, 2, 2}:当i=1时,nums[i] = -1,而nums[i-1] = -1,则说明-1在之前已经使用过了,即本次查找的a 和 上一次查找的a重复了。由于 上一次查找的left和right范围{-1, 2, 2} 包含了 本次查找的left和right范围{2, 2},所以在a相同的情况下,本次查找的三元组 是 上一次查找查找的三元组的子集,这就出现了三元组的重复,所以当nums[i] == nums[i-1]成立时,直接continue,nums[i]指向下一个元素

  3. 去重:对b和c去重,每次找到一个三元组后判断。假设有数组nums = {-2, -1, -1, 3, 3},当a=-2时,按照双指针法过程,会得到两个三元组结果:{-2, -1, 3}和{-2, -1, 3}。

    为什么会出现重复呢?分析来说:第一次循环b、c的下标left=1,right=4,a+b+c=0,然后left和right同时收缩。第二次循环b、c的下标left=2,right=3,a+b+c=0,所以这个三元组也被存放到结果集中了。明显这两次的结果出现了重复,原因就在于第一次循环中,nums[right] == nums[right+1]nums[left] == nums[left-1],因此left和right同时收缩后,b和c的结果还是一样的。对b和c去重,就要判断nums[right] == nums[right+1] 或 nums[left] == nums[left-1]是否成立,如果成立,则需要对right-- 或 对left++

代码实现

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        int left, right;
        for(int i=0; i<nums.size(); ++i)
        {
            if(nums[i] > 0)
            {
                break;
            }
            // 去重a
            if(i > 0 && nums[i] == nums[i-1])
            {
                continue;
            }
            left = i+1;
            right = nums.size()-1;
            while(right > left)
            {
                if(nums[i] + nums[left] + nums[right] > 0)
                {
                    right--;
                }else if(nums[i] + nums[left] + nums[right] < 0)
                {
                    left++;
                }else
                {
                    result.push_back(vector<int>{nums[i], nums[left], nums[right]});
                    left++;
                    right--;
                    // 去重b和c
                    while(right > left && nums[right] == nums[right+1])
                    {
                        right--;
                    }
                    while(right > left && nums[left] == nums[left-1])
                    {
                        left++;
                    }
                }
            }

        }
        return result;
    }
};
  • 时间复杂度: O(n^2),可以看到使用双指针减少了一层for循环,时间复杂度降低了一个量级
  • 空间复杂度: O(1)

18.四数之和

建议: 要比较一下,本题和 454.四数相加II 的区别,为什么 454.四数相加II 会简单很多,这个想明白了,对本题理解就深刻了。 本题 思路整体和 三数之和一样的,都是双指针,但写的时候 有很多小细节,需要注意,建议先看视频

题目链接:18. 四数之和 - 力扣(LeetCode)

思路

这道题和 三数之和 思路相同,都是使用排序+双指针法。注意这道题需要a+b+c+d == target,所以在剪枝上与 三数之和 有所不同。

整体思路:首先对nums进行排序,然后用两层for循环遍历数组nums,获得a = nums[i]和b = nums[j],在第二层for循环中,使用双指针left和right查找与a、b相匹配的c、d(四个变量 加和为target),去重操作与 三数之和 相同

剪枝+去重

  1. 剪枝:target可能为负值,所以用a > target剪枝是错误的,还需要加上条件a >= 0,因此剪枝条件为:a > target && a >= 0。第2级for循环的剪枝条件为:a+b > target && a+b >= 0
  2. 去重:与 三数之和 相同,对a、b去重需要判断nums[i] == nums[i-1],避免对重复的a、b进行查找;对c、d去重需要判断 nums[left] == nums[left-1] 以及 nums[right] == nums[right+1],若成立,则left++ 或 right–

注意:本题有溢出情况,需要将sum转化为long long型再进行判断

代码实现

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        int left, right;
        for(int i=0; i<nums.size(); ++i)
        {
            // 剪枝处理
            if(nums[i] > target && nums[i] >= 0)
            {
                break;
            }
            // 对nums[i]去重
            if(i>0 && nums[i] == nums[i-1])
            {
                continue;
            }
            for(int j=i+1; j<nums.size(); ++j)
            {
                // 2级剪枝处理
                if(nums[i] + nums[j] > target && nums[i] + nums[j] >= 0)
                {
                    break;
                }
                // 对nums[j]去重
                if(j > i+1 && nums[j] == nums[j-1])
                {
                    continue;
                }
                left = j+1;
                right = nums.size()-1;
                while(right > left)
                {
                    // 测试用例中有溢出情况,所以要用long long计算sum
                    long long sum = static_cast<long long>(nums[i]) + nums[j] + nums[left] + nums[right];
                    if(sum > target)
                    {
                        right--;
                    }else if(sum < target)
                    {
                        left++;
                    }else
                    {
                        result.push_back(vector<int>{nums[i], nums[j], nums[left], nums[right]});
                        // 找到答案时,双指针同时收缩
                        left++;
                        right--;
                        // 双指针去重
                        while(right > left && nums[right] == nums[right+1])
                        {
                            right--;
                        }
                        while(right > left && nums[left] == nums[left-1])
                        {
                            left++;
                        }
                    }
                }
            }

        }
        return result;
    }
};
  • 时间复杂度: O(n^3)
  • 空间复杂度: O(1)

复习:C++中的类型转换方法

static_cast

static_cast 是 C++ 中的一种类型转换运算符,用于在编译时执行显式类型转换。它提供了一种安全且明确的方式来进行类型转换,确保在转换过程中进行适当的检查,除了基本数据类型之间的转换(如int转换为double)、指针类型之间的转换(int* 转换为 double*)外,static_cast还可以进行类层次结构中的转换:

假设有一个基类 Base 和一个派生类 Derived

class Base {
public:
    virtual void show() {
        std::cout << "Base class" << std::endl;
    }
};

class Derived : public Base {
public:
    void show() override {
        std::cout << "Derived class" << std::endl;
    }
};

Base* basePtr = new Derived();
Derived* derivedPtr = static_cast<Derived*>(basePtr); // 将基类指针转换为派生类指针
derivedPtr->show(); // 输出 "Derived class"

dynamic_cast

用于运行时类型检查和转换,通常用于多态类型之间的转换。适用于具有继承关系的指针或引用类型之间的转换。

class Base {
    virtual void foo() {} // 必须有虚函数才能使用 dynamic_cast
};
class Derived : public Base {};

Base* basePtr = new Derived();
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); // 类层次结构中的转换
if (derivedPtr) {
    // 成功转换
} else {
    // 转换失败
}

reinterpret_cast

用于在几乎所有类型之间进行位级别的转换,适用于指针类型之间、整数类型与指针类型之间的转换。使用时需谨慎,因为它可能导致未定义行为。

int a = 10;
void* ptr = reinterpret_cast<void*>(&a); // 将 int* 转换为 void*
int* intPtr = reinterpret_cast<int*>(ptr); // 将 vo

感谢 chatgpt

总结

今天完成了四道题,这四道题都比较难,需要好好体会。四数相加II 使用的方法与 day6文章中的最后一题 两数之和 思想类似,但是又有所不同,主要体现在对map的键值对的设定。赎金信比较简单,需要注意magazine的每个字符只能用一次。三数之和四数之和是今天的重点,这两道题的难点在于如何去重四数相加II不需要去重,所以比这两道题简单。使用哈希法查找元素的时候,查找的结果是无顺序的,因此去重很麻烦,这两道题使用哈希法就不合适了。这两道题更好的解法是排序+双指针双指针降低了时间复杂度的数量级。用双指针替代两层for循环,这是一个很巧妙的思想。同时要多体会两道题中的剪枝+去重操作

双指针小结

截止目前,文章中涉及到的双指针法有:

  • 27.移除元素(opens new window)
  • 15.三数之和(opens new window)
  • 18.四数之和(opens new window)

链表相关双指针题目:

  • 206.反转链表(opens new window)
  • 19.删除链表的倒数第N个节点(opens new window)
  • 面试题 02.07. 链表相交(opens new window)
  • 142题.环形链表II(opens new window)

双指针法在字符串题目中还有很多应用,后面还会介绍到

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

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

相关文章

Pytorch使用教学1-Tensor的创建

0 导读 在我们不知道什么是深度学习计算框架时&#xff0c;我们可以把PyTorch看做是Python的第三方库&#xff0c;在PyTorch中定义了适用于深度学习的张量Tensor&#xff0c;以及张量的各类计算。就相当于NumPy中定义的Array和对应的科学计算方法&#xff0c;正是这些基本数据…

JVM系列(三) -类加载器及双亲委派模型介绍

在之前的文章中&#xff0c;介绍了类的加载过程中&#xff0c;我们有提到在加载阶段&#xff0c;通过一个类的全限定名来获取此类的二进制字节流操作&#xff0c;其实类加载器就是用来实现这个操作的。 在虚拟机中&#xff0c;任何一个类&#xff0c;都需要由加载它的类加载器…

【ffmpeg命令入门】添加水印

文章目录 前言什么是水印&#xff1f;为什么要添加水印&#xff1f;ffmpeg添加水印添加图片水印添加文字水印基本使用方法drawtext的参数 总结 前言 在视频制作和编辑的过程中&#xff0c;添加水印是一个常见且重要的步骤。水印不仅可以保护版权&#xff0c;还能用于品牌宣传和…

netty入门-4 Channel与ChannelFuture

Channel 基本类似于NIO中的Channel概念。作为读写数据的通道。 常见方法 close() 可以用来关闭 channelcloseFuture() 用来处理 channel 的关闭 sync 方法作用是同步等待 channel 关闭而 addListener 方法是异步等待 channel 关闭 pipeline() 方法添加处理器write() 方法将数…

Stable Diffusion基本原理通俗讲解

Stable Diffusion是一种基于深度学习的图像生成技术&#xff0c;它属于生成对抗网络&#xff08;GANs&#xff09;的一种。简单来说&#xff0c;Stable Diffusion通过训练一个生成器&#xff08;Generator&#xff09;和一个判别器&#xff08;Discriminator&#xff09;&#…

算法力扣刷题记录 五十八【701.二叉搜索树中的插入操作】

前言 本文是二叉搜索树操作。 二叉树篇继续。 一、题目阅读 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节…

【常见开源库的二次开发】基于openssl的加密与解密——SHA算法源码解析(六)

目录 一、SHA-1算法分析&#xff1a; 1.1 Merkle Tree可信树 1.2 源码实现&#xff1a; 1.3 哈希计算功能 1.4 两种算法的区别&#xff1a; 1.4.1 目的 1.4.2 实现机制 1.4.3 输出 1.4.4 应用场景&#xff1a; 1.4 运行演示&#xff1a; 二、SHA-2算法分析&#xff1a; 2.1哈…

【ESP32S3学习笔记】与有人AP520X路由器连接失败的问题

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 项目上新换了个路由器&#xff0c;结果发现ESP32模组连接不上&#xff0c;其他的路由器都正常。 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 对比log发现有问题的时候&#x…

智慧大棚数据库版

创建一个SMartBigHouse数据库 在数据库创建一个表用来存储数据 这边将id设为主键并将标识增量设为1 搭建Winfrom 搭建历史查询界面 串口数据&#xff0c;(这边是用的一个虚拟的串口工具&#xff0c;需要的话私) ModbusSerialMaster master;DataPointCollection wenduValues; //…

Win10使用VS Code远程连接Ubuntu服务器时遇到SSH公钥错误的解决方案

在使用Windows 10上的Visual Studio Code&#xff08;VS Code&#xff09;远程连接Ubuntu 20.04服务器时&#xff0c;遇到了以下错误&#xff1a; 错误的原因 这个错误消息表明&#xff0c;SSH 客户端检测到远程主机的 ECDSA 公钥已更改。可能是由于以下原因之一&#xff1a…

python—NumPy的基础(2)

文章目录 一维数组索引和切片一维数组索引和切片的使用一维数组负索引和切片的使用 二维数组的索引和切片索引直接获取使用坐标获取数组[x,y]二维数组负索引的使用切片数组的复制 改变数组的维度改变数组的维度 数组的拼接列表的拼接一维数组的拼接二维数组的拼接vstack 与hsta…

el-image预览图片点击遮盖处关闭预览

预览关闭按钮不明显 解决方式&#xff1a; 1.修改按钮样式明显点&#xff1a; //el-image 添加自定义类名&#xff0c;下文【test-image】代指 .test-image .el-icon-circle-close{ color:#fff; font-size:20px; ...改成很明显的样式 }2.使用事件监听&#xff0c;监听当前遮…

第十一章 数据结构

第十一章 数据结构 11.1 数组 数组是元素的顺序集合&#xff0c;通常这些元素具有相同的数据类型 索引表示元素在数组中的顺序号&#xff0c;顺序号从数组开始处计数 数组元素通过索引被独立给出了地址&#xff0c;数组整体上有一个名称&#xff0c;但每个元素利用数组的的…

TCP网络socket编程(面向连接)

Tcp面向链接、面向字节流和文件的读写非常类似&#xff08;&#xff09;&#xff1a;客户端创建套接字主动建立连接&#xff0c;服务器监听套接字一直等待连接的到来&#xff0c;监听到一个&#xff0c;就创建一个新的套接字用于IO 服务器&#xff1a; 创建套接字&#xff1a…

区块链和数据要素融合的价值及应用

一、数据要素面临的关键障碍 在构建数据要素基石的过程中&#xff0c;首要任务是明确并解决产权架构的难题&#xff0c;特别是使用权的确立与流转机制的顺畅&#xff0c;此乃数字经济蓬勃发展的命脉所在。一个高效的数据流转体系对于激发数据潜能、加速经济发展及优化数据资源…

TreeSelect增加可筛选功能

TreeSelect官方可筛选示例 <template><el-tree-selectv-model"value":data"data"filterablestyle"width: 240px"/><el-divider /><el-divider />filter node method:<el-tree-selectv-model"value":data&q…

使用torch_pruning对YOLOv8进行剪枝(新版、detect、segment)

torch_pruning库介绍 在结构修剪中&#xff0c;**Group被定义为深度网络中最小的可移除单元。**每个组由多个相互依赖的层组成&#xff0c;需要同时修剪这些层以保持最终结构的完整性。然而&#xff0c;深度网络通常表现出层与层之间错综复杂的依赖关系&#xff0c;这对结构修剪…

[大牛直播SDK]Windows平台RTMP直播推送模块功能设计

技术优势 全自研框架&#xff0c;易于扩展&#xff0c;自适应算法让延迟更低、采集编码传输效率更高&#xff1b;所有功能以SDK接口形式提供&#xff0c;所有状态&#xff0c;均有event回调&#xff0c;完美支持断网自动重连&#xff1b;SDK模块化&#xff0c;可和大牛直播播放…

DBeaver Ultimate 22.1.0 连接数据库(MySQL+Mongo+Clickhouse)

前言 继续书接上文 Docker Compose V2 安装常用数据库MySQL+Mongo,部署安装好之后我本来是找了一个web端的在线连接数据库的工具,但是使用过程中并不丝滑,最终还是选择了使用 DBeaver ,然后发现 mongo 还需要许可,又折腾整理了半下午,终于大功告成。 DBeaver 版本及说明…

SpringBoot集成Sharding-JDBC实现分库分表

本文已收录于专栏 《中间件合集》 目录 版本介绍背景介绍拆分方式集成并测试1.引入依赖2.创建库和表3.pom文件配置3.编写测试类Entity层Mapper接口MapperXML文件测试类 4.运行结果 自定义分片规则定义分片类编写pom文件 总结提升 版本介绍 SpringBoot的版本是&#xff1a; 2.3.…