【算法系列篇】分治-归并

news2024/11/25 6:27:25

在这里插入图片描述

文章目录

  • 前言
  • 什么是归并算法
  • 1. 排序数组
    • 1.1 题目要求
    • 1.2 做题思路
    • 1.3 Java代码实现
  • 2. 数组中逆序对
    • 2.1 题目要求
    • 2.2 做题思路
    • 2.3 Java代码实现
  • 3. 计算右侧小于当前元素的个数
    • 3.1 题目要求
    • 3.2 做题思路
    • 3.3 Java代码实现
  • 4. 翻转对
    • 4.1 题目要求
    • 4.2 做题思路
    • 4.3 Java代码实现
  • 总结

前言

上一篇算法文章,我们介绍了分治-快排的算法,今天我将为大家分享关于分治的另外一种算法——归并。

什么是归并算法

在这里插入图片描述
归并算法是一种常用的排序算法,它采用分治策略将待排序的数组分解为更小的子数组,然后逐步合并这些子数组以获得最终的有序数组。归并排序的主要思想是将两个有序的子数组合并成一个有序的数组。

归并算法通常包含以下步骤:

  1. 分解(Divide):将待排序的数组递归地分解为规模更小的子数组,直到每个子数组只有一个元素或为空。

  2. 解决(Conquer):通过递归地排序子数组,将其转化为有序的子数组。这通常是通过继续将子数组进一步分解并排序的方式实现的。

  3. 合并(Merge):将两个有序的子数组合并成一个有序的数组。该步骤的实现方式是比较两个子数组的元素,并按照顺序合并到一个新的数组中,直到所有元素都被合并。

归并排序的时间复杂度是O(nlogn),其中n是待排序数组的长度。它的主要优点包括:

  1. 稳定性:归并排序是一种稳定的排序算法,即相等元素的相对顺序不会被改变。

  2. 适用性:归并排序适用于各种数据结构,尤其在外部排序中,它对于大规模数据的排序效果明显。

然而,归并排序也存在一些缺点:

  1. 额外空间消耗:归并排序需要额外的空间来存储临时的子数组和合并结果,这可能对内存消耗造成一定影响。

  2. 递归调用:归并排序的实现通常使用递归调用,对于大规模数据的排序可能导致递归深度增加,从而增加了额外的函数调用开销。

总结而言,归并排序是一种高效、稳定的排序算法,通过分治策略将待排序的数组分解为更小的子数组,然后逐步合并这些子数组以获得最终的有序数组。尽管归并排序需要额外的空间和函数调用开销,但它在实践中被广泛使用,特别适用于对大规模数据进行排序。

1. 排序数组

https://leetcode.cn/problems/sort-an-array/

1.1 题目要求

给你一个整数数组 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 <= nums.length <= 5 * 104
  • -5 * 104 <= nums[i] <= 5 * 104
class Solution {
    public int[] sortArray(int[] nums) {

    }
}

1.2 做题思路

不知道大家是否做过将两个有序数组合并为一个有序数组,我们的归并算法就是通过将两个数组合并为一个有序数组来实现的。而归并的思想就是就一整个数组从中间将数组分为两个数组,然后再继续将这两个数组分别从中间分开,直到将这两部分的数组分为只有一个元素的两部分数组,然后将这两个数组通过合并两个数组的操作来进行合并,合并完成之后的数组就成为了一个有序的数组,然后继续将这两个有序的数组通过合并数组的操作继续进行合并,直到将这些数组合并为一个最大的数组。
在这里插入图片描述

在这里插入图片描述

1.3 Java代码实现

class Solution {
    //因为每一次递归都需要创建临时的数组来存储两个数组排序之后的结果,
    //每次都向申请内存,速度会很慢
    //所以我们直接申请一个跟nums同样大小的数组
    int[] tmp;
    public int[] sortArray(int[] nums) {
        int n = nums.length;
        tmp = new int[n];
        mergeSort(nums,0,n -1);
        return nums;
    }

    private void mergeSort(int[] nums, int left, int right) {
        //当数组中只有一个元素或者区间不成立的时候,结束递归
        if(left >= right) return;
        int mid = left + (right - left) / 2;
        //先排序mid左右两边的数组,最后在将左右两边的有序数组进行合并
        mergeSort(nums,left,mid);
        mergeSort(nums,mid + 1,right);

        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++];

        //将临时排序之后数组的结果更新到我们原本的数组中
        for(int j = left; j <= right; j++) nums[j] = tmp[j - left];
    }
}

在这里插入图片描述

2. 数组中逆序对

https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/description/

2.1 题目要求

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

示例 1:

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

限制:

  • 0 <= 数组长度 <= 50000
class Solution {
    public int reversePairs(int[] nums) {

    }
}

2.2 做题思路

我们先来看看如何使用暴力解法来解决这个问题:用两层循环来遍历数组,i 从 0 开始,j 则从 i 的下一个位置开始,看 j 所指向的位置是否小于 i 所指的位置,如果是则逆序对总数加一。这样虽然简单,但是时间复杂度达到了 O(N^2),是跑不过去的,那么我们就需要对暴力解法进行优化,问题就在于我们该如何优化呢?

这样想,如果我们将数组分为两个部分,先计算左边部分的数组中的所有逆序对,然后计算右边部分数组中的所有逆序对,最后在左边数组一次选择一个数字,看右边数组中是否元素能与左边数组中的那个元素构成逆序对,这样的思路其实跟暴力解法是相同的,时间复杂度都是 O(N^2),那么当我们分别在左边数组中和右边数组中找到了符合的逆序对的话,我们是否可以将这两部分数组进行排序呢?当进行了排序之后,再分别在左边数组中依次拿元素与右边数组中的元素进行比较,假设我们按照升序的方式进行排序,当左边部分遇到比右边数组部分大的元素的话,那么左边数组部分从这个元素开始到左边部分数组结束的位置是否都大于右边数组的该元素呢?
在这里插入图片描述
如果nums[cur1] < nums[cur2] 则继续让 cur1 向右移动,直到出现逆序对的情况,这样 cur1 和 cur2 指针都不用返回,就较少了很多的重复比较,使得时间复杂度提升为
O(N*logN)。

2.3 Java代码实现

(1)升序方法

class Solution {
    int[] tmp;
    public int reversePairs(int[] nums) {
        int n = nums.length;
        tmp = new int[n];
        return mergeSort(nums,0,n-1);
    }

    private int mergeSort(int[] nums, int left, int right) {
        if(left >= right) return 0;
        int mid = left + (right - left) / 2;
        //统计逆序对的数量
        int ret = 0;
        //计算左边数组中逆序对的数量
        ret += mergeSort(nums,left,mid);
        //计算右边数组中逆序对的数量
        ret += mergeSort(nums,mid + 1,right);

        int cur1 = left, cur2 = mid + 1,i = 0;
        while(cur1 <= mid && cur2 <= right) {
            //当nums[cur1] <= nums[cur2] 的时候,只需要进行合并数组的操作
            if(nums[cur1] <= nums[cur2]) tmp[i++] = nums[cur1++];
            //当nums[cur1] > nums[cur2] 的时候,需要更新逆序对的数量,同时也需要合并数组
            else {
                ret += mid - cur1 + 1;
                tmp[i++] = 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 - left];

        return ret;
    }
}

在这里插入图片描述
(2)降序方法
我们也可以用降序排列的方式来实现归并排序,只是当使用降序的时候,需要在右边数组中统计逆序对的数量,因为当遇到 nums[cur1] > nums[cur2] 的时候,如果还是统计左边数组 mid - cur1 + 1 作为逆序对的数量的话,那么当 cur2 向后移动的时候,再遇到 nums[cur1] > nums[cur2] 的时候就会出现重复的情况,所以当我们以降序的方式排序的时候需要在右边数组中统计逆序对的数量。
在这里插入图片描述

class Solution {
    int[] tmp;
    public int reversePairs(int[] nums) {
        int n = nums.length;
        tmp = new int[n];
        return mergeSort(nums,0,n-1);
    }

    private int mergeSort(int[] nums, int left, int right) {
        if(left >= right) return 0;
        int mid = left + (right - left) / 2;
        //统计逆序对的数量
        int ret = 0;
        //计算左边数组中逆序对的数量
        ret += mergeSort(nums,left,mid);
        //计算右边数组中逆序对的数量
        ret += mergeSort(nums,mid + 1,right);

        int cur1 = left, cur2 = mid + 1,i = 0;
        while(cur1 <= mid && cur2 <= right) {
            //当nums[cur1] <= nums[cur2] 的时候,只需要进行合并数组的操作
            if(nums[cur1] <= nums[cur2]) tmp[i++] = nums[cur2++];
            //当nums[cur1] > nums[cur2] 的时候,需要更新逆序对的数量,同时也需要合并数组
            else {
                ret += right - cur2 + 1;
                tmp[i++] = nums[cur1++];
            }
        }

        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 - left];

        return ret;
    }
}

在这里插入图片描述

3. 计算右侧小于当前元素的个数

https://leetcode.cn/problems/count-of-smaller-numbers-after-self/description/

3.1 题目要求

给你一个整数数组 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 个更小的元素

示例 2:

输入:nums = [-1]
输出:[0]

示例 3:

输入:nums = [-1,-1]
输出:[0,0]

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
class Solution {
    public List<Integer> countSmaller(int[] nums) {

    }
}

3.2 做题思路

这道题目跟上面的找逆序对的数量是类似的,逆序对是找前面的元素大于后面元素的个数,而这道题是需要找到数组中每个元素的之后的小于该元素的个数,也就是说这个题目返回的是多个数,而不是一个数。那么我们在使用分冶算法的过程中该如何记住对应数字的下标呢?因为在分冶的过程中加上排序,数组中元素的位置是不断变化的,但是这道题目按顺序返回数组中对用位置右边部分大小小于该位置元素的数量,所以这道题目如何记住原本数组对应元素的下标是很重要的。

那么我们如何记住原本数组元素的对应下标呢?我们可以创建一个 index 数组,当数组进行合并排序的时候,相应的 index 数组也跟着变化,这样就能使排序后数组对应位置的 index 数组中存放的是原本数组的下标。

在这里插入图片描述

3.3 Java代码实现

class Solution {
    int[] ret; //该数组中存放右侧小于当前元素的个数
    int[] index; //存放对应元素的下标
    int[] tmpNums; //排序后的临时数组
    int[] tmpIndex; //排序后对应元素的原本下标
    public List<Integer> countSmaller(int[] nums) {
        int n = nums.length;
        ret = new int[n];
        index = new int[n];
        //index 数组初始化
        for(int i = 0; i < n; i++) index[i] = i;
        tmpNums = new int[n];
        tmpIndex = new int[n];
        mergerSort(nums,0,n-1);
        List<Integer> list = new ArrayList<>();
        for(int x : ret) list.add(x);
        return list;
    }

    private void mergerSort(int[] nums, int left, int right) {
        if(left >= right) return;
        int mid = left + (right - left) / 2;
        mergerSort(nums,left,mid);
        mergerSort(nums,mid + 1,right);
        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];
        }
    } 
}

在这里插入图片描述

4. 翻转对

https://leetcode.cn/problems/reverse-pairs/description/

4.1 题目要求

给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。

你需要返回给定数组中的重要翻转对的数量。

示例 1:

输入: [1,3,2,3,1]
输出: 2

示例 2:

输入: [2,4,3,5,1]
输出: 3

注意:

  • 给定数组的长度不会超过50000。
  • 输入数组中的所有数字都在32位整数的表示范围内。
class Solution {
    public int reversePairs(int[] nums) {

    }
}

4.2 做题思路

这个题目跟前面的的两个题目都是类似的,只是这里不能在我们更新翻转对的时候就进行排序,因为翻转对的判断条件是 i < j 且 nums[i] > 2*nums[j],根据这个判断条件,我们不能判断出 nums[i] 和 nums[j] 哪个大,所以只能在更新完翻转对之后进行归并排序,其他的步骤基本上是类似的。
在这里插入图片描述

4.3 Java代码实现

(1)升序

class Solution {
    int[] tmp;
    public int reversePairs(int[] nums) {
        int n = nums.length;
        tmp = new int[n];
        return mergeSort(nums,0,n-1);
    }

    private int mergeSort(int[] nums, int left, int right) {
        if(left >= right) return 0;
        int ret = 0;
        int mid = left + (right - left) / 2;
        //统计左右两部分数组中翻转对的数量
        ret += mergeSort(nums,left,mid);
        ret += mergeSort(nums,mid + 1,right);
        int cur1 = left, cur2 = mid + 1, i = 0;
        while(cur2 <= right) {
        //这里需要使用nums[cur1] / 2.0 而不是nums[cur2] * 2,
        //因为可能会导致溢出
            while(cur1 <= mid && nums[cur1] / 2.0 <= nums[cur2]) cur1++;
            if(cur1 > mid) break;
            ret += mid - cur1 + 1;
            cur2++;
        }

		//升序
        cur1 = left;
        cur2 = mid + 1;
        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 - left];

        return ret;
    }
}

在这里插入图片描述

(2)降序

class Solution {
    int[] tmp;
    public int reversePairs(int[] nums) {
        int n = nums.length;
        tmp = new int[n];
        return mergeSort(nums,0,n-1);
    }

    private int mergeSort(int[] nums, int left, int right) {
        if(left >= right) return 0;
        int ret = 0;
        int mid = left + (right - left) / 2;
        ret += mergeSort(nums,left,mid);
        ret += mergeSort(nums,mid + 1,right);
        int cur1 = left, cur2 = mid + 1, i = 0;
        //降序
        while(cur1 <= mid) {
        //这里cur1不动,因为cur1向后移动只会越来越小,所以让cur2向后移动
            while(cur2 <= right && nums[cur1] / 2.0 <= nums[cur2]) cur2++;
            if(cur2 > right) break;
            ret += right - cur2 + 1;
            cur1++;
        }

        cur1 = left;
        cur2 = mid + 1;
        while(cur1 <= mid && cur2 <= right) {
            tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur2++] : nums[cur1++];
        }

        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 - left];

        return ret;
    }
}

在这里插入图片描述

总结

归并排序是一种高效而稳定的排序算法,它利用了分治策略,将待排序的数组分解为更小的子数组,并逐步合并这些子数组以获得最终的有序数组。

归并排序算法的核心思想是将待排序数组递归地分解为规模更小、有序的子数组,然后通过合并操作将这些子数组有序地合并成一个大的有序数组。这种分解和合并的过程直到最终合并成排序后的完整数组。

归并排序算法具有以下优点:

  1. 稳定性:归并排序是一种稳定的排序算法,即相等元素的相对顺序不会被改变。这使得它特别适用于对具有多关键字排序要求的情况。

  2. 高效性:归并排序的时间复杂度为O(nlogn),其中n是待排序数组的长度。它具有较好的性能表现,并适用于大规模数据的排序。

此外,归并排序算法还具有一定的弹性和灵活性。它可以通过优化合并操作的实现方式,减少额外空间的消耗。此外,归并排序也适用于外部排序,可以处理存储在外部存储介质中的大规模数据。

尽管归并排序算法需要额外的空间和函数调用开销,但由于其稳定性和较好的时间复杂度,它在实际应用中被广泛采用。

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

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

相关文章

金融信创,软件规划需关注自主安全及生态建设

软件信创化&#xff0c;就是信息技术软件应用创新发展的意思&#xff08;简称为“信创”&#xff09;。 相信在中国&#xff0c;企业对于“信创化”这个概念并不陌生。「国强则民强」&#xff0c;今年来中国经济的快速发展&#xff0c;受到了各大欧美强国的“卡脖子”操作的影…

CNN(七):ResNeXt-50算法的思考

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 在进行ResNeXt-50实战练习时&#xff0c;我也跟其他学员一样有这个疑惑&#xff0c;如下图所示&#xff1a; 反复查看代码&#xff0c;仍然有…

探讨前后端分离开发的优势、实践以及如何实现更好的用户体验?

随着互联网技术的迅猛发展&#xff0c;前后端分离开发已经成为现代软件开发的一种重要趋势。这种开发模式将前端和后端的开发工作分开&#xff0c;通过清晰的接口协议进行通信&#xff0c;旨在优化开发流程、提升团队协作效率&#xff0c;并最终改善用户体验。本文将深入探讨前…

Elasticsearch——Docker单机部署安装

文章目录 1 简介2 Docker安装与配置2.1 安装Docker2.2 配置Docker镜像加速器2.3 调整Docker资源限制 3 准备Elasticsearch Docker镜像3.1 下载Elasticsearch镜像3.2 自定义镜像配置3.3执行Docker Compose 4 运行Elasticsearch容器4.1 创建Elasticsearch容器4.2 修改配置文件4.3…

Mac 搭建本地服务器

文章目录 一、启动服务器二、添加文件到本地服务三、手机/其他电脑 访问本机服务器 MacOS 自带Apatch 服务器。所以我这里选择Apatch服务器搭建 一、启动服务器 在safari中输入 http://127.0.0.1/ &#xff0c;如果页面出现 it works&#xff0c;则代表访问成功。启动服务器 …

开开心心带你学习MySQL数据库之第五篇

&#x1f63a;欢迎来到我的博客, 记得点赞&#x1f44d;收藏⭐️留言✍️&#x1f431; &#x1f409;做为一个怪兽&#xff0c;我的目标是少消灭一个奥特曼&#x1f409; &#x1f4d6;希望我写的博客对你有所帮助,如有不足,请指正&#x1f4d6; chatgpt 是否能够代替程序猿?…

AI时代:探索机器学习与深度学习的融合之旅

文章目录 1. 机器学习和深度学习简介1.1 机器学习1.2 深度学习 2. 为什么融合是必要的&#xff1f;2.1 数据增强2.2 模型融合 3. 深入分析&#xff1a;案例研究3.1 传统机器学习方法3.2 深度学习方法3.3 融合方法 4. 未来展望结论 &#x1f389;欢迎来到AIGC人工智能专栏~AI时代…

【力扣每日一题】2023.9.6 最深叶节点的最近公共祖先

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一棵二叉树&#xff0c;让我们找出所有最深叶子节点的最近公共祖先。 我们一步一步剖析&#xff0c;我们先找出最深叶子节点&…

SpringBoot Admin监控平台《一》平台搭建及基础介绍

一、SpringBoot Admin简介 1.1.简介 Spring Boot Admin是一个管理和监控Spring Boot应用程序的开源项目&#xff0c;在对单一应用服务监控的同时也提供了集群监控方案&#xff0c;支持通过eureka、consul、zookeeper等注册中心的方式实现多服务监控与管理。Spring Boot Admin…

npm修改为国内镜像

npm config get registry 查看下载地址&#xff0c;默认是https://registry.npmjs.org/ 这是国外的地址&#xff0c;npm下载很慢 npm config set registry https://registry.npmmirror.com/ 使用此指令&#xff0c;修改为淘宝镜像&#xff0c;输入指令后检查是否修改成功 …

02-Tomcat打破双亲委派机制

Tomcat 如果使用默认的双亲委派类加载机制行不行&#xff1f; 我们思考一下&#xff1a;Tomcat是个web容器&#xff0c; 那么它要解决什么问题&#xff1a; 一个web容器可能需要部署两个应用程序&#xff0c;不同的应用程序可能会依赖同一个第三方类库的不同版本&#xff0c;…

配电网智能软开关(sop)规划模型matlab

目录 1 主要内容 2 部分程序 3 程序结果 1 主要内容 该程序参考文献《基于改进灵敏度分析的有源配电网智能软开关优化配置》&#xff0c;采用二阶锥算法&#xff0c;以改进的IEEE33节点配电系统模型作为分析对象&#xff0c;以联络开关位置作为sop安装备选位置&#xff0c;以…

最适合运动的耳机类型是什么、最适合运动的耳机推荐

运动和音乐天生就是绝佳的组合&#xff0c;因此对于许多运动爱好者来说&#xff0c;耳机一直都是必备的装备。通过音乐&#xff0c;我们可以带着节奏感去探索世界&#xff0c;让我们的运动过程更加有动力。 一款优秀的运动耳机需要具备舒适的佩戴感、稳固性和防水性能。作为一位…

实践和项目:解决实际问题时,选择合适的数据结构和算法

文章目录 选择合适的数据结构数组链表栈队列树图哈希表 选择合适的算法实践和项目 &#x1f389;欢迎来到数据结构学习专栏~实践和项目&#xff1a;解决实际问题时&#xff0c;选择合适的数据结构和算法 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT…

水处理行业污水处理厂电能质量监测与治理系统解决方案-安科瑞黄安南

摘要&#xff1a;在水处理行业供配电系统中&#xff0c;涉及曝气风机、提升泵、污泥脱水设备等感性负荷设备&#xff0c;导致异步电动机产生较多无功功率和大量的谐波&#xff0c;使部分设备表现出轻载或不满载运行状况降低功率因数&#xff0c;以及谐波对配电系统、负载产生较…

leetcode 234. 回文链表

2023.9.5 本题先将链表的节点值移到数组中&#xff0c;再用双指针去判断该数组是否为回文的即可。 代码如下&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* …

ST表(转载自其它博主)

文章目录 一、简介二、Leetcode题目补充1. 2023/9/6 更新 一、简介 ST表&#xff1a;https://zhuanlan.zhihu.com/p/123360481 二、Leetcode题目补充 1. 2023/9/6 更新 239. 滑动窗口最大值 class Solution {public int[] maxSlidingWindow(int[] nums, int k) {//记录数…

vue3项目,点击分页器,列表接口请求两次的问题

接手别人做的项目&#xff0c;出现了一个分页器bug&#xff0c;vue3element plus&#xff0c;记录一下。 点击分页器&#xff0c;却出现了调用两次列表接口的情况&#xff0c;并且第二次请求&#xff0c;分页器的pageNum自动变成1&#xff0c;这样就导致了分页器bug&#xff0…

Git 命令行查看仓库信息

目录 查看系统config ​编辑查看当前用户&#xff08;global&#xff09;配置 查看当前仓库配置信息 查看系统config git config --system --list 1 查看当前用户&#xff08;global&#xff09;配置 git config --global --list 1 查到的是email , name 等ssl签名信息&a…

不再产生火花:光耦合器继电器如何确保您的电路安全

近年来&#xff0c;对电子设备和电路的需求激增&#xff0c;推动了对更安全、更可靠的组件的需求。确保电路安全的关键元件之一是光耦继电器。这些不起眼的设备在保护电路和防止潜在危险情况&#xff08;例如火花和电气过载&#xff09;方面发挥着重要作用。 什么是光耦继电器…