【优选算法篇】分治乾坤,万物归一:在重组中窥见无声的秩序

文章目录

  • 分治专题(二):归并排序的核心思想与进阶应用
    • 前言
    • 第二章:归并排序的应用与延展
      • 2.1 归并排序(medium)
        • 解法(归并排序)
        • C++ 代码实现
        • 易错点提示
        • 时间复杂度和空间复杂度
      • 2.2 数组中的逆序对(hard)
        • 解法(利用归并排序的过程 — 分治)
        • 核心步骤与实现细节
        • C++ 代码实现
        • 易错点提示
        • 时间复杂度和空间复杂度
      • 2.3 计算右侧小于当前元素的个数(hard)
        • 解法(利用归并排序的过程 — 分治)
        • 核心步骤
        • C++ 代码实现
        • 易错点提示
        • 时间复杂度和空间复杂度
      • 2.4 翻转对(hard)
        • 解法(归并排序 — 分治)
        • 核心步骤与实现细节
        • C++ 代码实现
        • 易错点提示
        • 时间复杂度和空间复杂度
        • 优化点
    • 写在最后

分治专题(二):归并排序的核心思想与进阶应用

🚀 欢迎讨论:如果您对内容有任何疑问或见解,欢迎在评论区留言。

👍 点赞、收藏与分享:如果觉得这篇文章对您有帮助,请点赞、收藏并分享给更多朋友。

💡 分享给更多人:一起学习分治策略,掌握归并排序的精髓!


前言

上篇:【优选算法篇】化繁为简,见素抱朴:从乱象中重构秩序的艺术

归并排序是经典的分治法应用,其核心在于“分而治之”的思想。通过不断划分,将一个复杂问题逐步拆解成若干规模更小的子问题,以递归方式求解,再将解合并,从而解决初始问题。本文将围绕归并排序的基本原理,结合排序数组的题目,深入剖析归并排序在分治中的实际应用。


第二章:归并排序的应用与延展

2.1 归并排序(medium)

题目链接:912. 排序数组

题目描述

给定一个整数数组 nums,请将该数组按升序排列。

示例 1

  • 输入:nums = [5,2,3,1]
  • 输出:[1,2,3,5]

示例 2

  • 输入:nums = [5,1,1,2,0,0]
  • 输出:[0,0,1,1,2,5]

解法(归并排序)

算法思路

归并排序的过程充分体现了“分而治之”的思想,基本步骤分为以下两部分:

  1. :将数组一分为二,递归地继续分割,直到每个子数组的长度为 1,确保所有分块都已排序。

  2. :将两个已排序的子数组合并成一个有序数组,最终返回整个数组的有序结果。

具体步骤

  • 使用中间点将数组分成 [left, mid][mid + 1, right] 两部分。
  • 递归对左右区间进行排序。
  • 在排序好的左右子数组中,使用双指针将较小的元素依次合并到临时数组 tmp 中。
  • 合并完成后,将 tmp 数组的内容拷贝回原数组。

C++ 代码实现
class Solution {vector<int> tmp; // 临时数组用于存储合并结果
public:vector<int> sortArray(vector<int>& nums) {tmp.resize(nums.size());mergeSort(nums, 0, nums.size() - 1);return nums;}// 归并排序void mergeSort(vector<int>& nums, int left, int right) {if (left >= right) return; // 递归终止条件// 1. 分区int mid = (left + right) / 2;mergeSort(nums, left, mid);mergeSort(nums, mid + 1, right);// 2. 合并两个已排序数组int cur1 = left, cur2 = mid + 1, i = 0;while (cur1 <= mid && cur2 <= right) {tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];}while (cur1 <= mid) tmp[i++] = nums[cur1++]; // 左边剩余部分while (cur2 <= right) tmp[i++] = nums[cur2++]; // 右边剩余部分// 3. 拷贝回原数组for (int j = 0; j < i; ++j) {nums[left + j] = tmp[j];}}
};

易错点提示
  1. 递归终止条件

    • mergeSort 函数中,left >= right 时停止递归,以防止无穷递归导致的栈溢出。
  2. 合并逻辑

    • cur1cur2 分别指向左、右子数组的起始位置,使用 tmp 存储合并结果。确保在所有元素都合并后,将 tmp 拷贝回 nums 中。
  3. 临时数组的使用

    • 临时数组 tmp 存储每一轮合并结果,以确保排序结果被完整保留到下一轮递归。

时间复杂度和空间复杂度
  • 时间复杂度O(n log n)。每轮合并的时间复杂度为 O(n),分区深度为 log n
  • 空间复杂度O(n),临时数组 tmp 占用额外空间。

2.2 数组中的逆序对(hard)

题目链接:剑指 Offer 51. 数组中的逆序对

题目描述

在一个数组中的两个数字,如果前面的一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

示例 1

  • 输入:[7,5,6,4]
  • 输出:5

解法(利用归并排序的过程 — 分治)

算法思路

归并排序求逆序数是经典的方法。在归并排序的合并过程中,我们可以顺便统计出逆序对的数量,这样可以避免暴力统计的 O(n^2) 时间复杂度。

逆序对的产生方式可分为三种情况:

  1. 左数组中的元素逆序。
  2. 右数组中的元素逆序。
  3. 左数组和右数组中的元素形成逆序。

归并排序过程可以分为两个步骤:

  1. :将数组一分为二,不断划分,直到每个子数组长度为1。
  2. :将左右子数组合并成一个有序数组的过程中,统计逆序对的数量。

核心步骤与实现细节
  1. 为什么可以利用归并排序求逆序对?

    因为在归并排序的过程中,我们通过分治的方法将数组拆分成左右两部分。每部分内部的逆序对可以分别在排序的过程中统计。最终在归并左右数组时,可以统计那些横跨左右数组的逆序对,这三者相加即为总的逆序对数。

  2. 核心问题:如何在合并两个有序数组的过程中统计逆序对的数量?

    在合并左右两个已排序的数组时,可以高效统计出横跨两个数组的逆序对数。考虑以下例子:

    假设有两个有序序列 left = [5, 7, 9]right = [4, 5, 8]
    目标是计算在合并的过程中 left 中的元素大于 right 中的元素的情况数量。

  3. 合并并统计逆序对的过程

    定义指针 cur1 遍历 left 数组,cur2 遍历 right 数组。
    定义 ret 记录逆序对的数量,help 数组临时存储排序的结果。

    • 第一轮

      • 比较 left[cur1]right[cur2],如果 left[cur1] > right[cur2],则意味着从 cur1 到末尾的元素都大于 right[cur2](因为 left 是有序的)。我们可以确定逆序对数量并将结果累加到 ret
      • left[cur1] <= right[cur2],则将 left[cur1] 添加到 help 数组中。
    • 处理剩余元素:若一侧数组元素遍历完,剩余元素直接添加到 help 数组即可,不会再产生新的逆序对。


C++ 代码实现
class Solution {int tmp[50010]; // 临时数组
public:int reversePairs(vector<int>& nums) {return mergeSort(nums, 0, nums.size() - 1);}int mergeSort(vector<int>& nums, int left, int right) {if (left >= right) return 0; // 递归终止条件int ret = 0;// 1. 找中间点,将数组分成两部分int mid = (left + right) >> 1;// 2. 左、右部分的逆序对数量ret += mergeSort(nums, left, mid);ret += mergeSort(nums, mid + 1, right);// 3. 合并并统计逆序对数量int cur1 = left, cur2 = mid + 1, i = 0;while (cur1 <= mid && cur2 <= right) {if (nums[cur1] <= nums[cur2]) {tmp[i++] = nums[cur1++]; // 左侧元素较小,无逆序对} else {ret += mid - cur1 + 1; // 右侧元素小,统计逆序对tmp[i++] = nums[cur2++];}}// 4. 处理剩余元素while (cur1 <= mid) tmp[i++] = nums[cur1++];while (cur2 <= right) tmp[i++] = nums[cur2++];// 5. 将 tmp 数组内容拷贝回原数组for (int j = left; j <= right; j++) {nums[j] = tmp[j - left];}return ret;}
};

易错点提示
  1. 递归终止条件

    • left >= right 时,表示已将数组分割到单个元素,递归停止返回0。
  2. 统计逆序对

    • nums[cur1] > nums[cur2] 时,说明 left[cur1] 及后面的所有元素都大于 right[cur2],则这些元素与 right[cur2] 构成逆序对。统计并更新 ret 的值。
  3. 处理剩余元素

    • 若左数组或右数组有剩余,则直接将剩余部分加入到 tmp,因为剩余部分不会形成逆序对。
  4. 拷贝回原数组

    • 最后将 tmp 的排序结果拷贝回 nums,确保在递归的上一级合并时数组依旧有序。

时间复杂度和空间复杂度
  • 时间复杂度O(n log n)。归并排序的分治递归实现使得时间复杂度达到 O(n log n)
  • 空间复杂度O(n),需要额外的数组存储合并结果。

2.3 计算右侧小于当前元素的个数(hard)

题目链接:315. 计算右侧小于当前元素的个数

题目描述

给你一个整数数组 nums ,按要求返回一个新数组 counts
数组 counts 有如下性质:counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。

示例 1

  • 输入:nums = [5,2,6,1]
  • 输出:[2,1,1,0]

解释

  • 5 的右侧有 2 个更小的元素(2 和 1)。
  • 2 的右侧有 1 个更小的元素(1)。
  • 6 的右侧有 1 个更小的元素(1)。
  • 1 的右侧有 0 个更小的元素。

解法(利用归并排序的过程 — 分治)

算法思路

本题和求数组中的逆序对非常类似,但与逆序对的统计不同之处在于:

  • 需要返回一个数组 counts,记录每个元素右侧更小的元素数量,而不是单一的逆序对总数。
  • 归并排序过程中,除了排序,还需要记录排序过程中元素的索引位置的变化。

核心步骤
  1. 辅助数组和索引绑定

    • 定义一个 index 数组,用于记录元素对应的原始索引,确保元素与下标绑定在一起。
    • ret 数组存储每个元素右侧更小元素的数量。
  2. 递归排序

    • 递归地对数组进行分治排序,并统计左右子数组中每个元素右侧更小的元素数量。
  3. 合并排序并统计逆序对

    • 当合并两个有序数组时,如果发现左侧的某个元素大于右侧的当前元素,则说明该左侧元素右侧的所有元素都小于它。将这些逆序对数量累加到对应的 ret 索引上。
    • 同时,完成左右子数组的归并操作。

C++ 代码实现
class Solution {vector<int> ret;        // 结果数组vector<int> index;      // 记录元素的原始下标int tmpNums[100010];    // 临时数组用于排序int tmpIndex[100010];   // 临时数组用于记录索引排序public:vector<int> countSmaller(vector<int>& nums) {int n = nums.size();ret.resize(n, 0);       // 初始化结果数组为0index.resize(n);        // 初始化下标数组for (int i = 0; i < n; i++) {index[i] = i;       // 初始时,索引与数组位置一一对应}mergeSort(nums, 0, n - 1);return ret;}void mergeSort(vector<int>& nums, int left, int right) {if (left >= right) return;// 1. 分区int mid = (left + right) / 2;// 2. 递归处理左右子区间mergeSort(nums, left, mid);mergeSort(nums, mid + 1, right);// 3. 合并并统计逆序对int cur1 = left, cur2 = mid + 1, i = 0;while (cur1 <= mid && cur2 <= right) {if (nums[cur1] <= nums[cur2]) {tmpNums[i] = nums[cur2];tmpIndex[i++] = index[cur2++];} else {// 当前左侧元素大于右侧元素,统计逆序对ret[index[cur1]] += right - cur2 + 1;tmpNums[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}}// 处理剩余元素while (cur1 <= mid) {tmpNums[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}while (cur2 <= right) {tmpNums[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}// 拷贝回原数组for (int j = left; j <= right; j++) {nums[j] = tmpNums[j - left];index[j] = tmpIndex[j - left];}}
};

易错点提示
  1. 确保索引正确绑定

    • 在每次合并的过程中,索引数组 index 也需要同步排序,以保证结果数组 ret 的统计准确。
  2. 统计逆序对的逻辑

    • nums[cur1] > nums[cur2] 时,说明从 cur2right 的所有元素都小于 nums[cur1],需要将这些数量累加到 ret[index[cur1]]
  3. 递归终止条件

    • left >= right 时停止递归,避免无效操作。

时间复杂度和空间复杂度
  • 时间复杂度O(n log n)。分治递归的时间复杂度是 O(log n),每次合并的时间复杂度是 O(n)
  • 空间复杂度O(n)。需要额外的临时数组 tmpNumstmpIndex 进行合并排序。

2.4 翻转对(hard)

题目链接:493. 翻转对

题目描述

给定一个数组 nums,如果 i < jnums[i] > 2 * nums[j],我们就将 (i, j) 称作一个重要翻转对。
你需要返回给定数组中的重要翻转对的数量。

示例 1

  • 输入:nums = [1,3,2,3,1]
  • 输出:2

解法(归并排序 — 分治)

算法思路

翻转对的统计与逆序对非常类似,都可以利用 归并排序 的思想,将问题分解为三部分:

  1. 左数组中的翻转对数量。
  2. 右数组中的翻转对数量。
  3. 左右数组合并时的翻转对数量。

由于翻转对要求的是 nums[i] > 2 * nums[j],直接在合并排序时统计会比较困难,因此:

  • 我们在归并排序前,提前统计 左右两部分数组中满足条件的翻转对数量。
  • 在统计完成后,再进行归并排序。

核心步骤与实现细节
  1. 统计翻转对数量

    • 使用两个指针 cur1cur2,分别遍历左、右子数组。
    • 对于每个左数组元素 nums[cur1],找到右数组中第一个不满足 nums[cur1] > 2 * nums[cur2] 的位置 cur2
    • 此时,cur2 - mid - 1 即为当前 cur1 的翻转对数量,累加到结果中。
  2. 合并两个有序数组

    • 合并时,按照归并排序的逻辑,将两个子数组排序,并写入临时数组。
  3. 递归分治

    • 每次划分数组为 [left, mid][mid + 1, right],递归统计翻转对数量并排序。

C++ 代码实现
class Solution {int tmp[50010]; // 临时数组用于合并排序
public:int reversePairs(vector<int>& nums) {return mergeSort(nums, 0, nums.size() - 1);}int mergeSort(vector<int>& nums, int left, int right) {if (left >= right) return 0;int ret = 0;// 1. 分区int mid = (left + right) / 2;// 2. 递归计算左右区间的翻转对数量ret += mergeSort(nums, left, mid);ret += mergeSort(nums, mid + 1, right);// 3. 统计翻转对数量int cur1 = left, cur2 = mid + 1;while (cur1 <= mid) {while (cur2 <= right && nums[cur2] * 2 < nums[cur1]) {cur2++;}ret += cur2 - mid - 1;cur1++;}// 4. 合并两个有序数组cur1 = left, cur2 = mid + 1;int i = left;while (cur1 <= mid && cur2 <= right) {tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];}while (cur1 <= mid) tmp[i++] = nums[cur1++];while (cur2 <= right) tmp[i++] = nums[cur2++];for (int j = left; j <= right; j++) {nums[j] = tmp[j];}return ret;}
};

易错点提示
  1. 统计翻转对的逻辑

    • 必须确保 cur2 指针只向右移动,不会回退,避免重复计算。
    • 注意翻转对的判断条件 nums[cur1] > 2 * nums[cur2],需要考虑到浮点运算可能导致的精度问题,因此 2 * nums[cur2] 可能需要写成 nums[cur1] > 2LL * nums[cur2]
  2. 归并排序的逻辑

    • 合并时,确保临时数组和原数组的元素同步,避免在递归的上一层出错。
  3. 边界条件

    • 单元素或空数组的递归终止条件是 left >= right

时间复杂度和空间复杂度
  • 时间复杂度O(n log n)

    • 每次递归的深度是 log n,每层递归需要合并排序和统计翻转对,复杂度为 O(n)
  • 空间复杂度O(n)

    • 使用了额外的临时数组 tmp 进行排序。

优化点
  1. 使用更大的临时数组(避免频繁分配内存)。
  2. 在统计翻转对时,提前检查是否有可能的翻转对,减少无意义的遍历。

通过以上方法,翻转对的数量可以在 O(n log n) 的时间复杂度内高效统计。

写在最后

在本次归并排序专题中,我们以经典的分治思想为核心,逐层剖析了归并排序的精髓及其在算法中的高级应用。从数组排序到统计逆序对,再到复杂的翻转对和右侧更小元素计数,归并排序不仅是解决基础问题的利器,更是攻克高阶难题的关键。我们以逐步深入的方式,从基础实现到优化分析,贯穿了分治思想的深度与广度。

分治法的核心在于“分而治之”,通过不断将大问题拆解为小问题,并利用递归与合并的方式重新组合结果。在归并排序中,借助临时数组和指针操作,我们能够高效完成排序,并在此过程中完成复杂的统计任务。它不仅展现了算法的美学,更体现了计算机科学中化繁为简的哲学。

通过归并排序的深入学习,我们不仅掌握了分治策略的实现,更体验了算法优化的艺术。期待这篇文章能为读者打开分治法的大门,让你在算法学习中游刃有余!


以上就是关于【优选算法篇】分治乾坤,万物归一:在重组中窥见无声的秩序的内容啦,各位大佬有什么问题欢迎在评论区指正,或者私信我也是可以的啦,您的支持是我创作的最大动力!❤️

在这里插入图片描述

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

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

相关文章

生产环境centos8 Red Hat8部署ansible and 一键部署mysql两主两从ansible脚本预告

一、各节点服务器创建lvm逻辑卷组 1.初始化磁盘为物理卷&#xff08;PV&#xff09; 命令&#xff1a;sudo pvcreate /dev/vdb 2.创建卷组&#xff08;VG&#xff09; 命令&#xff1a;sudo vgcreate db_vg /dev/vdb 3.创建逻辑卷&#xff08;LV&#xff09; 命令&#xff1a;s…

CNN神经网络

CNN 一 基本概述二 基础知识三 经典案例 今天跟大家聊聊人工智能中的神经网络模型相关内容。神经网络内容庞大,篇幅有限本文主要讲述其中的CNN神经网络模型。 一 基本概述 深度学习(Deep Learning)特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网…

【Ubuntu24.04】VirtualBox安装ubuntu-live-server24.04

目录 0 背景1 下载镜像2 安装虚拟机3 安装UbuntuServer24.044 配置基本环境5 总结0 背景 有了远程连接工具之后,似乎作为服务器的Ubuntu24.04桌面版有点备受冷落了,桌面版的Ubuntu24.04的优势是图形化桌面,是作为一个日常工作的系统来用的,就像Windows,如果要作为服务器来…

【策略模式】最佳实践——Spring IoC实现策略模式全流程深度解析

简介 策略模式是一种行为型设计模式&#xff0c;它定义了一系列算法&#xff0c;并将每一个算法封装起来&#xff0c;使它们可以互相替换&#xff0c;并且使算法的变化不会影响使用算法的客户端。策略模式通过将具体的业务逻辑从上下文&#xff08;Context&#xff09;中剥离出…

企业项目级IDEA设置类注释、方法注释模板(仅增加@author和@date)

文章目录 前言一 设置类注释1.1 添加模板1.2 复制配置 二 设置方法注释2.1 添加模版2.2 设置模版2.3 设置参数变量2.4 配置对应快捷键2.5 配置对应作用域2.6 使用方式 说明 前言 公司代码规范中&#xff0c;需要在标准JavaDoc注释的基础上加上作者和日期。网上虽然有很多现成的…

单片机学习笔记 2. LED灯闪烁

目录 0、实现的功能 1、Keil工程 2、代码实现 0、实现的功能 LED灯闪烁 1、Keil工程 闪烁原理&#xff1a;需要进行软件延时达到人眼能分辨出来的效果。常用的延时方法有软件延时和定时器延时。此次先进行软件延时 具体操作步骤和之前的笔记一致。此次主要利用无符号整型的范…

编辑器vim 命令的学习

1.编辑器Vim 1.vim是一个专注的编辑器 2.是一个支持多模式的编辑器 1.1见一见&#xff1a; vim 的本质也是一条命令 退出来&#xff1a;-> Shift:q 先创建一个文件 再打开这个文件 进入后先按 I 然后就可以输入了 输入完后&#xff0c;保存退出 按Esc --> 来到最后一…

调用门提权

在我写的2.保护模式&#xff0b;段探测这篇文章中&#xff0c;我们提到了S位对于段描述符的控制&#xff0c;之前我们已经介绍了代码段和数据段&#xff0c;现在我们来把目光转到系统段 在这么多中结构里面&#xff0c;我们今天要介绍的就是编号为12的&#xff0c;32位调用门 结…

langchain模型及I/O的封装

langchain安装&#xff1a;pip install langchain-openai https://python.langchain.com/v0.2/docs/integrations/platforms/openai/ 注意&#xff1a;安装后&#xff0c;我们需要在环境变量中配置OPENAI_API_KEY&#xff0c;langchain会自动获取 1.模型的封装 指令生成式模…

阿里斑马智行 2025届秋招 NLP算法工程师

文章目录 个人情况一面/技术面 1h二面/技术面 1h三面/HR面 20min 个人情况 先说一下个人情况&#xff1a; 学校情况&#xff1a;211本中9硕&#xff0c;本硕学校都一般&#xff0c;本硕都是计算机科班&#xff0c;但研究方向并不是NLP&#xff0c;而是图表示学习论文情况&…

谈一谈QThread::CurrentThread和this->thread

QThread::CurrentThread是指的当前函数调用者者所在的线程 this->thread是指的当前对象所在的线程&#xff08;对象创建出来的时候所在的线程&#xff09; Qt文档说明 CurrentThread返回一个指向管理当前执行线程的QThread的指针 thread返回对象所在的线程 这两个函数所…

深度学习实验十一 卷积神经网络(2)——基于LeNet实现手写体数字识别实验

目录 一、数据 二、模型构建 三、模型训练及评价 四、打印参数量和计算量 五、模型预测 附&#xff1a;完整可运行代码 实验大致步骤&#xff1a; 一、数据 下载网站&#xff1a;MNIST数据集 之前的官网不能下载数据集了&#xff0c;403了&#xff0c;所以找到一个类似…

Python语法便捷查询

一、Python基础语法&#xff1a; (1)注释&#xff1a; (2)标识符&#xff1a; 简介&#xff1a;标识符的格式限制和C语言一样 (3)字符串定义方法&#xff1a; (4)字符串拼接&#xff1a; (5)字符串的格式化&#xff08;占位拼接&#xff09;&#xff1a; 和C语言的printf类…

Ansys Maxwell - 3PH 感应电机 - 第 2 部分 - 机床工具包 ACT

本篇博文是“Ansys Maxwell&#xff1a;3PH 感应电机 - 力和热耦合”的延续。在本篇博文中&#xff0c;我将展示如何使用 Ansys Machine Toolkit ACT 开发扭矩与速度曲线&#xff08;一系列性能曲线&#xff0c;包括效率图&#xff09;&#xff0c;以评估在 Ansys Maxwell 中建…

【含开题报告+文档+PPT+源码】基于springboot的教师评价系统的设计与实现

开题报告 随着信息技术的迅猛发展&#xff0c;教育信息化已成为现代教育的必然趋势。教研室作为高校教学管理的重要机构&#xff0c;肩负着提升教学质量、推动教学改革的重要使命。然而&#xff0c;传统的教学管理方式往往存在效率低下、数据分散、管理不便等问题&#xff0c;…

用 Python 从零开始创建神经网络(八):梯度、偏导数和链式法则

梯度、偏导数和链式法则 引言1. 偏导数2. 和的偏导数3. 乘法的偏导数4. Max 的偏导数5. 梯度&#xff08;The Gradient&#xff09;6. 链式法则&#xff08;The Chain Rule&#xff09; 引言 在我们继续编写我们的神经网络代码之前&#xff0c;最后两个需要解决的难题是梯度和…

并查集 poj 2524,1611,1703,2236,2492,1988 练习集【蓝桥杯备赛】

目录 前言 并查集优势 Ubiquitous Religions poj 2524 问题描述 问题分析 代码 The Suspects poj 1611 问题描述 问题分析 代码 Wireless Network poj 2236 问题描述 问题分析 代码 分类 带权并查集合 权值树构建步骤 Find them, Catch them poj 1703 问题描述 问题分…

zabbix监控tomcat

1. 准备JDK环境 #vim /etc/profile export JAVA_HOME/usr/local/jdk export TOMCAT_HOME/usr/local/tomcat export PATH$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$TOMCAT_HOMOE/bin [rootCentOS8 ~]# source /etc/profile [rootCentOS8 ~]# java -version openjdk version &q…

Nuget For Unity插件介绍

NuGet for Unity&#xff1a;提升 Unity 开发效率的利器 NuGet 是 .NET 开发生态中不可或缺的包管理工具,你可以将其理解为Unity的Assets Store或者UPM,里面有很多库可以帮助我们提高开发效率。当你想使用一个库,恰好这个库没什么依赖(比如newtonjson),那么下载包并找到Dll直接…

如何在 Ubuntu 上安装 Mattermost 团队协作工具

简介 Mattermost 是一个开源、自托管的通信平台&#xff0c;专为团队协作设计。它类似于 Slack&#xff0c;提供聊天、消息传递和集成功能。Mattermost 在重视数据隐私的组织中特别受欢迎&#xff0c;因为它允许团队在自己的服务器上管理通信。以下是 Mattermost 的一些关键特…