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

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

文章目录

    • 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']++;}// 然后检查这些字符是否能组成ransomNotefor(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;}// 去重aif(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和cwhile(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计算sumlong 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)

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

相关文章:

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

文章目录 454.四数相加II思路 383.赎金信思路 15.三数之和思路剪枝去重 18.四数之和思路剪枝去重复习&#xff1a;C中的类型转换方法 总结 今天是哈希表专题的第二天 废话不多说&#xff0c;直接上题目 454.四数相加II 建议&#xff1a;本题是 使用map 巧妙解决的问题&#x…...

Spark实时(三):Structured Streaming入门案例

文章目录 Structured Streaming入门案例 一、Scala代码如下 二、Java 代码如下 三、以上代码注意点如下 Structured Streaming入门案例 我们使用Structured Streaming来监控socket数据统计WordCount。这里我们使用Spark版本为3.4.3版本&#xff0c;首先在Maven pom文件中导…...

《Java初阶数据结构》----4.<线性表---Stack栈和Queue队列>

前言 大家好&#xff0c;我目前在学习java。之前也学了一段时间&#xff0c;但是没有发布博客。时间过的真的很快。我会利用好这个暑假&#xff0c;来复习之前学过的内容&#xff0c;并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区…...

Android SurfaceFlinger——关联EGL三要素(二十七)

通过前面的文章我们得到了 EGL 的三要素——Display、Surface 和 Context。其中,Display 是一个图形显示系统或者硬件屏幕,Surface 代表一个可以被渲染的图像缓冲区,Context 包含了 OpenGL ES 的状态信息和资源,它是执行 OpenGL 命令的环境。下一步就是调用 eglMakeCurrent…...

Unity3D之TCP网络通信(客户端)

文章目录 概述TCP核心类异步机制 Unity中创建TCP客户端Unity中其它脚本获取TCP客户端接受到的数据后续改进 本文将以Unity3D应用项目作为客户端去连接制定的服务器为例进行相关说明。 Unity官网参考资料&#xff1a; https://developer.unity.cn/projects/6572ea1bedbc2a001ef…...

Kotlin 中 标准库函数

在 Kotlin 中&#xff0c;标准库提供了许多实用的函数&#xff0c;这些函数可以帮助简化代码、提高效率&#xff0c;以下是一些常用的标准库函数及其功能&#xff1a; let: let 函数允许你在对象上执行一个操作&#xff0c;并返回结果。它通常与安全调用操作符 ?. 一起使用&a…...

【教学类-69-01】20240721铠甲勇士扑克牌(随机14个数字+字母)涂色(男孩篇)

背景需求&#xff1a; 【教学类-68-01】20240720裙子涂色&#xff08;女孩篇&#xff09;-CSDN博客文章浏览阅读250次。【教学类-68-01】20240720裙子涂色&#xff08;女孩篇&#xff09;https://blog.csdn.net/reasonsummer/article/details/140578153 前期制作了女孩涂色延…...

Adobe“加速”创意人士开启设计新篇章

近日&#xff0c;Adobe公司宣布了其行业领先的专业设计应用程序——Adobe Illustrator和Adobe Photoshop的突破性创新。这一重大更新不仅为创意专业人士带来了前所未有的设计可能性和工作效率提升&#xff0c;还让不论是插画师、设计师还是摄影师&#xff0c;都能从中受益并创作…...

释疑 803-(1)概述 精炼提纯版

目录 习题 1-01计算机网络可以向用户提供哪些服务? 1-02 试简述分组交换的要点。 1-03 试从多个方面比较电路交换、报文交换和分组交换的主要优缺点。 1-05 互联网基础结构的发展大致分为哪几个阶段?请指出这几个阶段最主要的特点。 1-06 简述互联网标准制定的几个阶段…...

人工智能与机器学习原理精解【6】

文章目录 数值优化基础理论凹凸性定义在国外与国内存在不同国内定义国外定义总结示例与说明注意事项 国内凹凸性二阶定义的例子凹函数例子凸函数例子 凸函数&#xff08;convex function&#xff09;的开口方向凸函数的二阶导数凸函数的二阶定义单变量函数的二阶定义多变量函数…...

JDK、JRE、JVM之间的关系

JDK是Java的开发环境&#xff0c;用JDK开发了JAVA程序后&#xff0c;通过JDK中的编译程序&#xff08;javac&#xff09;将java文件编译成字节码文件&#xff0c;作为运行环境的JRE&#xff0c;字节码文件在JRE上运行&#xff0c;作为虚拟机的JVM解析这些字节码&#xff0c;映射…...

redis构建集群时,一直Waiting for the cluster to join

redis构建集群时&#xff0c;一直Waiting for the cluster to join 前置条件参考 前置条件 这是我搭建的集群相关信息&#xff0c;三台虚拟机&#xff0c;分别是一主一从。在将所有虚拟机中redis服务器用到的tcp端口都打开之后&#xff0c;进行构建集群。但是出现上面的情况。 …...

C++之类与对象(2)

前言 今天将步入学习类的默认成员函数&#xff0c;本节讲解其中的构造函数和析构函数。 1.类的默认成员函数 在 C 中&#xff0c;如果一个类没有显式定义某些成员函数&#xff0c;编译器会自动为该类生成默认的成员函数。以下是编译器可能会生成的默认成员函数&#xff1a; 默…...

「树形结构」基于 Antd 实现一个动态增加子节点+可拖拽的树

效果 如图所示 实现 import { createRoot } from react-dom/client; import React, { useState } from react; import { Tree, Input, Button } from antd; import { PlusOutlined } from ant-design/icons;const { TreeNode } Tree; const { Search } Input;const ini…...

ubuntu那些ppa源在哪

Ubuntu中的 PPA 终极指南 - UBUNTU粉丝之家 什么是PPA PPA 代表个人包存档。 PPA 允许应用程序开发人员和 Linux 用户创建自己的存储库来分发软件。 使用 PPA&#xff0c;您可以轻松获取较新的软件版本或官方 Ubuntu 存储库无法提供的软件。 为什么使用PPA&#xff1f; 正如…...

20240724-然后用idea创建一个Java项目/配置maven环境/本地仓储配置

1.创建一个java项目 &#xff08;1&#xff09;点击页面的create project&#xff0c;然后next &#xff08;2&#xff09;不勾选&#xff0c;继续next &#xff08;3&#xff09;选择新项目名称&#xff0c;新项目路径&#xff0c;然后Finsh&#xff0c;在新打开的页面选择…...

PaddleOCR-PP-OCRv4推理详解及部署实现(下)

目录 前言1. 检测模型1.1 预处理1.2 后处理1.3 推理 2. 方向分类器模型2.1 预处理2.2 后处理2.3 推理 3. 识别模型3.1 预处理3.2 后处理3.3 推理 4. PP-OCRv4部署4.1 源码下载4.2 环境配置4.2.1 配置CMakeLists.txt4.2.2 配置Makefile 4.3 ONNX导出4.4 engine生成4.4.1 检测模型…...

【Golang 面试基础题】每日 5 题(二)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…...

状态模式与订单状态机的实现

状态模式 状态模式&#xff08;State Design Pattern&#xff09;是一种行为设计模式&#xff0c;用于在对象的内部状态改变时改变其行为。这种模式可以将状态的变化封装在状态对象中&#xff0c;使得对象在状态变化时不会影响到其他代码&#xff0c;提升了代码的灵活性和可维…...

【MSP430】MSP430是什么?与STM32对比哪个性能更佳?

一、MSP430是什么&#xff1f; MSP430F5529LP是一款由德州仪器&#xff08;TI&#xff09;推出的16位微控制器单元&#xff08;MCU&#xff09;开发板&#xff0c;具有USB功能&#xff0c;内存配置为128KB闪存和8KB RAM&#xff0c;工作频率高达25MHz。 这款MCU以其高性能和多…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...

Spring AOP代理对象生成原理

代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】&#xff0c;这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...

【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法

使用 ROS1-Noetic 和 mavros v1.20.1&#xff0c; 携带经纬度海拔的话题主要有三个&#xff1a; /mavros/global_position/raw/fix/mavros/gpsstatus/gps1/raw/mavros/global_position/global 查看 mavros 源码&#xff0c;来分析他们的发布过程。发现前两个话题都对应了同一…...

Linux入门课的思维导图

耗时两周&#xff0c;终于把慕课网上的Linux的基础入门课实操、总结完了&#xff01; 第一次以Blog的形式做学习记录&#xff0c;过程很有意思&#xff0c;但也很耗时。 课程时长5h&#xff0c;涉及到很多专有名词&#xff0c;要去逐个查找&#xff0c;以前接触过的概念因为时…...

vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能

vxe-table vue 表格复选框多选数据&#xff0c;实现快捷键 Shift 批量选择功能 查看官网&#xff1a;https://vxetable.cn 效果 代码 通过 checkbox-config.isShift 启用批量选中,启用后按住快捷键和鼠标批量选取 <template><div><vxe-grid v-bind"gri…...

MySQL基本操作(续)

第3章&#xff1a;MySQL基本操作&#xff08;续&#xff09; 3.3 表操作 表是关系型数据库中存储数据的基本结构&#xff0c;由行和列组成。在MySQL中&#xff0c;表操作包括创建表、查看表结构、修改表和删除表等。本节将详细介绍这些操作。 3.3.1 创建表 在MySQL中&#…...

【学习记录】使用 Kali Linux 与 Hashcat 进行 WiFi 安全分析:合法的安全测试指南

文章目录 &#x1f4cc; 前言&#x1f9f0; 一、前期准备✅ 安装 Kali Linux✅ 获取支持监听模式的无线网卡 &#x1f6e0; 二、使用 Kali Linux 进行 WiFi 安全测试步骤 1&#xff1a;插入无线网卡并确认识别步骤 2&#xff1a;开启监听模式步骤 3&#xff1a;扫描附近的 WiFi…...