写对二分查找不是套模板并往里面填空,需要仔细分析题意

news2024/12/31 7:32:54

视频讲解:《算法不好玩》二分查找专题 (已经录制的部分,能够帮助大家完全搞懂二分查找算法,非常适合初学的朋友们)。

2022 年 12 月 27 日补充:有时间的话请大家先看上面的视频,2 倍速看完就好,知道前因后果以后,再做题就更有方向了。文字题解的内容还是更偏向于做题,直接给出了最优解,没有一步一步探索的过程这里帮大家归纳一下重点:有一些问题可以在循环之中找到答案,所以写法是 while(left <= right) ,循环体内是三个分支。更多的问题需要等到退出循环以后得到答案,所以写法是 while(left < right) ,循环体内是两个分支。

实际上「二分查找」没有多少东西,一点儿也不难,觉得「二分查找」难写对的朋友,请认认真真做几个「二分查找」的问题,弄清楚每一行代码的意思,遇到死循环的时候仔细调试,弄清楚逻辑关系,而不要套别人给你写好的模版。

有很多问题 mid 有可能是问题的答案,所以不能排除掉,所以你看到的代码是 left = midright = mid,不要有思维定式,代码一定要写成 left = mid + 1 或者 right = mid - 1,而应该看题目怎么说。看清问题比记忆模版重要得多,不同的问题答案不一样,如果题目的意思都没弄清楚,怎么解决问题。

如果你在学习二分查找的过程中有很多问题,你可以先记下来,不用急着与解决它们,等你做了足够多的问题,有了足够的思考以后,你的问题会慢慢得到解答,我的学习过程也是这样,这个过程是很充实的。

阅读提示:内容比较多,核心思想帮大家归纳一下。如果没有时间看,建议把后面的问题做一下。

题解核心内容:所有模板都一样,不可以套模板,而应该 仔细看题(解题的关键在认真读题),分析清楚题目要找的答案需要满足什么性质。采用两边夹的方式,每一轮把待搜索区间分成两个部分,排除掉一定不是答案的区间,最后左右指针重合的地方就是我们要找的元素。

重要的事情说三遍

  • 如果你看我写的「二分查找」题解,请忘记掉「左闭右开」这件事情,它会对你有所干扰
  • 如果你看我写的「二分查找」题解,请忘记掉「左闭右开」这件事情,它会对你有所干扰
  • 如果你看我写的「二分查找」题解,请忘记掉「左闭右开」这件事情,它会对你有所干扰

说明:我所有的关于「二分查找」法的题解,都会明确地标注「下一轮搜索区间是什么」,进而设置左边界 left 和 右边界 right。在我写的「二分查找」题解里,while(left < right) 不表示 循环不变量的区间定义是 [left..right),也就是说,如果我分析出,下一轮搜索区间是 [mid..10],我会设置 right = 10,而不会设置 right = 11

while(left < right) 只表示它本来的意思:在 left < right 进入循环体。不要给它附加别的意思,这没有逻辑


写在前面的话

写对「二分查找」的重点,从来不在于「二分查找」我们用的是哪一个模板(所有的模板背后的逻辑都一样),更不在于我们设置的区间是「左闭右闭」还是「左开右闭」。而在于 认真看题、仔细分析题意,根据题目的条件和要求思考如何缩减区间,清楚地知道每一轮在什么样的情况下,搜索的范围是什么,进而设置左右边界。

我们需要分析清楚题目的意思,分析清楚要找的答案需要满足什么性质。应该清楚模板具体的用法,明白需要根据题意灵活处理、需要变通的地方,不可以认为每一行代码都是模板规定死的写法,不可以盲目套用、死记硬背

二分查找只有一个思想,那就是:逐步缩小搜索区间

本题解向大家介绍的,使用 leftright 向中间靠拢的方法,有一个非常强的语义,那就是:leftright 重合的时候,我们就找到了问题的答案,使用这种写法有一个巨大的好处,那就是返回值不需要考虑返回 left 还是 right,因为退出循环以后,它们是重合的。

重要的事情说三遍:

  • 不是因为这种方法有用,而是因为很多问题就这么设计来着,一定要等到最后才能确定问题的解,在很多时候,不能在循环体中找到答案。
  • 不是因为这种方法有用,而是因为很多问题就这么设计来着,一定要等到最后才能确定问题的解,在很多时候,不能在循环体中找到答案。
  • 不是因为这种方法有用,而是因为很多问题就这么设计来着,一定要等到最后才能确定问题的解,在很多时候,不能在循环体中找到答案。

这一类问题解决的过程如下图所示:

在这里插入图片描述

在做题的过程中,会遇到两个难点:

  1. mid 的时候,有些时候需要 +1,这是因为需要避免死循环;
  2. 只把区间分成两个部分,这是因为:只有这样,退出循环的时候才有 leftright 重合,我们才敢说,找到了问题的答案。

这两个难点,在练习的过程中,会逐渐清晰,不用着急一下子搞懂,事实上也不难理解。

本题解分为三个部分:

  • 第一部分:本题题解。

如果只想看本题(「力扣」第 35 题)怎么解的,可以只看这里。

  • 第二部分:二分查找常见问题回答。

重点概括了评论区常见的问题。

  • 第三部分:二分查找题解列表(包含文字题解和视频题解)。

我花了很多时间做的教程,详细讲解了我是如何分析这些问题的,相信一定对你有帮助。


第一部分:本题题解

这一部分一定要分析清楚:

  • 题目要找的元素是:第一个大于等于 target 的元素的下标;
  • 数组的长度 len 也有可能是问题的答案,「参考代码 2」设置 right = len 不是因为设置区间是「左闭右开」,而是因为 len 本来就有可能是问题的答案。

上面 2 个小点,都需要仔细分析题意和几个示例得到,任何模板都不能回答这样的问题。

题意分析

根据示例,分析题目要我们返回的「插入元素的位置」是什么。

根据「示例 3」:

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

我们知道:如果目标元素 严格大于 输入数组中的最后一个元素,题目需要我们返回数组的最后一个元素的下标 +1(也就是数组的长度)。

又根据「示例 2」:

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

我们知道:题目要我们返回第 1 1 1 个 大于等于 目标元素 2 的下标(分析出这一点非常重要),因此返回 1。等于的情况可以看「示例 1」。

思路分析

在有序数组中查找,可以使用「二分查找」。

根据「题意分析」中对示例的描述:

  • 情况 1:如果当前 mid 看到的数值严格小于 target,那么 mid 以及 mid 左边的所有元素就一定不是「插入元素的位置」,因此下一轮搜索区间是 [mid + 1..right],下一轮把 left 移动到 mid + 1 位置,因此设置 left = mid + 1
  • 情况 2:否则,如果 mid 看到的数值大于等于 target,那么 mid 可能是「插入元素的位置」mid 的右边一定不存在「插入元素的位置」。如果 mid 的左边不存在「插入元素的位置」,我们才可以说 mid 是「插入元素的位置」。因此下一轮搜索区间是 [left..mid],下一轮把 right 移动到 mid 位置,因此设置 right = mid

说明:上面的两点中,「情况 2」其实不用分析得那么细致, 因为只要「情况 1」的区间分析是正确的,「情况 2」一定是「情况 1」得到的区间的反面区间。

参考代码 1

public class Solution {

    public int searchInsert(int[] nums, int target) {
        int len = nums.length;
        // 特殊判断
        if (nums[len - 1] < target) {
            return len;
        }

        // 程序走到这里一定有 nums[len - 1] >= target,插入位置在区间 [0..len - 1]
        int left = 0;
        int right = len - 1;
        // 在区间 nums[left..right] 里查找第 1 个大于等于 target 的元素的下标
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target){
                // 下一轮搜索的区间是 [mid + 1..right]
                left = mid + 1;
            } else {
                // 下一轮搜索的区间是 [left..mid]
                right = mid;
            }
        }
        return left;
    }
}

说明while (left < right) 表示当 leftright 重合的时候,搜索终止。根据题意和示例,区间 nums[left..right] 里一定存在「插入元素的位置」,且 while 循环里只把区间分成两个部分,退出循环的时候一定有 left == right 成立,因此返回 left 或者 right 都可以。

复杂度分析

  • 时间复杂度: O ( log ⁡ N ) O(\log N) O(logN),这里 N N N 是输入数组的长度;
  • 空间复杂度: O ( 1 ) O(1) O(1)

既然 len 也有可能是答案,可以在初始化的时候,把 right 设置成 len,在一开始的时候就不需要特殊判断了。

参考代码 2

public class Solution {

    public int searchInsert(int[] nums, int target) {
        int len = nums.length;
        int left = 0;
        int right = len;
        // 在区间 nums[left..right] 里查找第 1 个大于等于 target 的元素的下标
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target){
                // 下一轮搜索的区间是 [mid + 1..right]
                left = mid + 1;
            } else {
                // 下一轮搜索的区间是 [left..mid]
                right = mid;
            }
        }
        return left;
    }
}

复杂度分析:(同参考代码 1)


第二部分:二分查找常见问题回答

温馨提示

  • 以下内容有点多,但是都是非常简单直观的内容。我整理了在我的题解下网友的诸多疑问,进行了总结,希望大家能认真看看;
  • 真的踏踏实实做完一些二分查找的问题,已经有了足够的思考,就会觉得没有那么难。

问题 1:为什么在你的题解里 while (left < right) 表示「左闭右闭」区间

回答while (left < right) 不表示搜索区间为「左闭右开」,也不表示搜索区间为「左闭右闭」, 它们没有因果关系while (left < right) 只表示它本来的意思:循环可以继续的条件是 left < right边界如何设置,这一点完全是人为定义的

表示一个区间,最直接的表示就是左闭右闭区间。例如:我们想表示搜索的范围是 1, 2, 3, 4, 5, 6, 7, 8, 9 ,很自然地会表示成 [1..9] ,我们也会说这些数是 19 之间的数,包括 19。正常情况下,不会说:这些数在 110 之间,不包括 10

只看到 while (left < right) 里的 < ,不能说明右边界不能取到。真正看区间表示应该看左右边界到底如何设置,如果我们分析出下一轮搜索的范围是 [left..mid] 而设置 right = mid + 1,才表示搜索区间为「左闭右开」区间 。这是因为 [left..right) = [left..mid + 1) = [left..mid]

可以看到,任何一个「左闭右开」区间都对应一个「左闭右闭」区间。我们已经可以确切地知道要搜索的数的右边界是什么, 没有必要把右边界再 + 1 +1 +1

重点:真正写对「二分查找」,从来不在于我们把区间写成了「左闭右开」还是「左闭右闭」,而是 在于我们能够根据题意:得到某种单调性,和可以逐步缩小搜索规模的条件,进而准确地设计可以使得搜索区间缩小的条件

问题 2:二分查找是不是要求数组一定是有序的?

回答:不一定。

「力扣」上有一些问题输入数组不是有序的,例如「旋转有序数组」「山脉数组」(题号在第三部分的习题列表里),这些问题题目给出的是「接近有序」的数组,依然可以使用「二分查找」,这是因为这些数组都有规律可循,可以根据看到的 num[mid] 的值,推测两侧元素的性质,进而 缩小搜索区间

还有一类问题,例如「力扣」第 287 题,这一类题目不是在输入数组上做二分,而是在输入数组的最小值 min 和最大值 max 组成的连续整数数组上查找一个数,即搜索区间是 [min..max],这个区间是单调的。

这一类问题的特点是:题目要我们找一个整数,这个整数的范围是确定的,可以使用「二分查找」,这样的问题叫「二分答案」。很多引入「二分查找」的例子,其实就是在做「二分答案」,《幸运 52》猜价格游戏,就是在用「二分查找」的思想猜到商品准确的价格。

问题 3:为什么有一些二分查找取 mid 的时候,括号里要加 1?

这是因为 int mid = (left + right) / 2 在区间里有偶数个元素的时候,mid 只能取到位于左边的中间数,要想取到位于右边的中间数,就需要在括号里加 1。

为什么要取右边中间数呢?这是因为在区间里 只有 2 2 2 个元素的时候,把 [left..right] 划分成 [left..mid - 1][mid..right] 这两个区间,int mid = (left + right) / 2 这种取法不能把搜索区间缩小。

理解这件事情最典型的例子是「力扣」第 69 题,详细的分析和调试在 这里。

总之就是为了:避免死循环

问题 4:能不能解释一下其它「二分查找」的模板为什么是对的?

这个问题我已经回答在 题目求助|二分查找不同实现方法细节困惑。我再补充一下:不管是哪一种模板,都不会回答看到的 mid 的值以后如何设计条件,把区间进行正确的划分,以及:

  • 在某种条件下,mid 的值是否可以取到;
  • 下一轮搜索是在 mid 的左边还是右边继续查找。

「模板一」告诉你全部把 mid 排除掉,用 ans 做补救,保证不会错过答案,「模板三」告诉你全部把 mid 保留,退出循环以后 [left..right] 里剩下两个数,再单独判断一下。它们有「限制死的地方」,所以一定要再理解清楚题意的情况下,正确使用。这些模板没有好坏和优劣之分,它们背后解决问题的思想是一样的。

再次强调一下:我们学习算法不是背了一个模板然后往里面填空,而是我们真的清楚写的代码每一步在做什么,每一步搜索的范围是什么。更不是因为把区间表示成「左闭右开」而使得问题变得简单。

问题 5:什么时候 rightlen ?什么时候 right = len - 1

回答:这种问题就像你问我什么时候向左边找,什么时候向右边找,我的回答都是:看题目,每个问题的答案都未必一样

先回答什么时候 rightlen ?什么时候 right = len - 1?就像本题(「力扣」第 35 题),「示例 3」就告诉我们,len 是有可能成为答案的,所以设置 right = len,上面第一部分「参考代码 2」的写法,「参考代码 1」已经做了一次判断,在 len 不可能是答案的情况下,才设置 right = len - 1。这一点请不要扯上区间「左闭右开」和「左闭右闭」了,毫无关系。

「力扣」第 34 题,查找 target 在有序数组出现的第一次的位置和最后一次出现的位置,既然是数组里的位置,最小是 0,最大是 len - 1

用这两个例子还是想说:到底设置的搜索区间是什么,看题目怎么说。

再回答什么时候向左边找,什么时候向右边找。回答还是 看题目:输入数组是升序还是降序,决定了向左边找还是向右边找。

总结:如果不能够正确理解题意,不去真正仔细的做练习、分析和总结,凭空想到底这些问题改怎么做,抱怨「二分查找」细节多、难是没有用的。其实根本没有想象中的难。用最直接、简单的想法看待「二分查找」就可以。

下面再为大家总结一下「二分查找」的重点。

二分查找重点概括

  • 写成 while(left < right) ,退出循环的时候有 left == right 成立,好处是:不用判断应该返回 left 还是 right
  • 区间 [left..right] 划分只有以下两种情况:
    • 分成 [left..mid][mid + 1..right],分别对应 right = midleft = mid + 1
    • 分成 [left..mid - 1][mid..right],分别对应 right = mid - 1left = mid,这种情况下。需要将 int mid = (left + right) / 2 改成 int mid = (left + right + 1) / 2,否则会出现死循环,这一点不用记,出现死循环的时候,把 leftright 的值打印出来看一下就很清楚了
  • 退出循环 left == right,如果可以确定区间 [left..right] 一定有解,直接返回 left 就可以,否则还需要对 left 这个位置单独做一次判断
  • 始终保持不变的是:在区间 [left..right] 里查找目标元素。

关于如何写对二分查找,二分查找的详细讲解,可以查看我编写的 LeetBook 的「二分查找」 章节。


第三部分:二分查找题解列表(包含文字题解和视频题解)

以下是练习(我写过很多「二分查找习题列表」,我暂时先把它们汇总在这里)。

提示:这些问题都不应该套模板去做,而应该在真正弄清楚题意(明确地知道题目要我们找的元素的性质)以后,对看到的元素进行合理的分支判断,进而清楚搜索的范围。

二分查找的基本思想是「减而治之」,即逐渐缩小问题规模。以下的二分查找问题,我们都不应该背下来,而应该在练习的过程中逐渐掌握分析问题、解决问题的方法。

可以采用的循环不变量是:总是在区间 [left..right] 里查找目标元素。采用左闭右开区间只会增加麻烦。

遇到问题的时候,一定需要仔细调试,使用最最基本的打印输出语句,针对错误测试用例,发现出错的原因。

题型一:二分求下标(在数组中查找符合条件的元素的下标)

说明

  • 第 704 题:二分查找的最原始问题,使用两边夹的二分查找方法需要后处理(退出循环以后,还需要判断 leftright 位置的值是不是问题的答案);

  • 第 34 题、第 35 题:需要明白这一类问题的共同特点,请见 这里;

  • 第 300 题:特别经典的一道「动态规划」,二分查找的思路基于「动态规划」的状态定义得到,代码很像第 35 题;

  • 第 658 题:这个问题二分的写法需要做复杂的分类讨论,可以放在以后做;

  • 第 4 题:二分查找里最难的问题,重点在于理解:① 为什么是在短数组里找边界;② 深刻理解搜索边界的意义。

题号链接题解
704二分查找(简单)
35搜索插入位置(简单)【视频讲解】、文字题解
300最长上升子序列(中等)文字题解
34在排序数组中查找元素的第一个和最后一个位置(简单)【视频讲解】、文字题解
611有效三角形的个数文字题解
658找到 K 个最接近的元素(中等)文字题解
436寻找右区间(中等)文字题解
1237找出给定方程的正整数解(中等)
1300转变数组后最接近目标值的数组和(中等)文字题解
4寻找两个有序数组的中位数(困难)【视频讲解】、文字题解

使用二分查找的前提不一定非要是「有序数组」。旋转有序数组(下表前 4 题)、山脉数组(下表后 2 题)里的查找问题也可以使用「二分查找」。这些问题的解决思路是:利用 局部单调性,逐步缩小搜索区间。

题号链接题解
33搜索旋转排序数组(中等)文字题解
81搜索旋转排序数组 II(中等)文字题解
153寻找旋转排序数组中的最小值(中等)文字题解
154寻找旋转排序数组中的最小值 II(困难)文字题解
852山脉数组的峰顶索引(简单)
1095山脉数组中查找目标值(中等)【视频讲解】、文字题解

题型二:二分答案(在一个有范围的区间里搜索一个整数)

如果题目要我们找一个整数,这个整数有确定的范围,可以通过二分查找逐渐缩小范围,最后逼近到一个数。

定位一个有范围的整数,这件事情也叫「二分答案」或者叫「二分结果」。如果题目要求的是一个整数,这个整数有明确的范围,可以考虑使用二分查找。

事实上,二分答案是我们最早接触的二分查找的场景。「幸运 52」里猜价格游戏,就是「二分查找」算法的典型应用:先随便猜一个数,如果猜中,游戏结束。如果猜大了,往小猜;如果猜小了,往大猜。

说明

  • 第 69 题:在一个整数范围里查找一个整数,也是二分查找法的应用场景;
  • 第 275 题:这个问题题解题意得花很多时间,可以跳过不做;
  • 第 278 题:在一个整数范围里查找一个整数,不是在输入数组里使用二分查找。这个问题二分查找的解法很反常规(不应该用时间换空间),知道即可。
题号链接题解
69x 的平方根(简单)文字题解
287寻找重复数(中等)文字题解
374猜数字大小(简单)文字题解
275H指数 II(中等)文字题解
1283使结果不超过阈值的最小除数(中等)文字题解
1292元素和小于等于阈值的正方形的最大边长(中等)

题型三:二分答案的升级版(每一次缩小区间的时候都需要遍历数组)

说明:这一类问题本质上还是「题型二」(二分答案),但是初学的时候会觉得有一些绕。这一类问题的问法都差不多,关键字是「连续」、「正整数」,请大家注意捕捉题目中这样的关键信息。

这里给出的问题解法都一样,会一题等于会其它题。问题的场景会告诉我们:目标变量和另一个变量有相关关系(一般是线性关系),目标变量的性质不好推测,但是另一个变量的性质相对容易推测(满足某种意义上的单调性)。这样的问题的判别函数通常会写成一个函数的形式。

这一类问题可以统称为「 最大值极小化 」问题,最原始的问题场景是木棍切割问题,这道题的原始问题是「力扣」第 410 题(分割数组的最大值(困难))。

思路是这样的:

  • 分析出题目要我们找一个整数,这个整数有范围,所以可以用二分查找;
  • 分析出 单调性,一般来说是一个变量 a 的值大了,另一个变量 b 的值就变小,而「另一个变量的值」 b 有限制,因此可以通过调整 a 的值达到控制 b 的效果;
  • 这一类问题的题目条件一定会给出 连续正整数 这样的关键字。如果没有,问题场景也一定蕴含了这两个关键信息。

参考资料:

  • 二分查找之「最大值极小化」相关问题及解题步骤
  • 二分查找之「最大值极小化」例题选讲

以下给出的问题无一例外。

题号链接题解
875爱吃香蕉的珂珂(中等)文字题解
410分割数组的最大值(困难)文字题解
LCP 12小张刷题计划(中等)题解在第 410 题题解里
1011在 D 天内送达包裹的能力(中等)
1482制作 m 束花所需的最少天数(中等)题解在第 1300 题题解里
1552两球之间的磁力(中等)

补充:「力扣」第 209 题:长度最小的子数组(中等),这道题可以使用「前缀和 + 二分查找」或者「滑动窗口」来做,一定要想清楚,为什么可以使用这些方法。

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

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

相关文章

JAVA基础 - 使用CommandLine解析命令行参数

它是什么 commons-cli 是一个强大而的开源的命令行参数传递与解析的解决方案&#xff0c;用于接收MAIN方法的args参数。可以通过设置短选项&#xff08;即选项名简写&#xff09;、长选项&#xff08;即全写&#xff09;、设置是否需要携带选项参数&#xff08;指定为 false 时…

jenkins python api与json api不同

查看jenkins的python api与json api&#xff0c;感觉两者相差不多&#xff0c;但还是有所区别&#xff0c;所以用BeyondCompare进行对比分析。 1、jenkins base url的api对比 左侧的为&#xff1a;http://server:port/jenkins/api/python?prettytrue 右侧的为&#xff1a;h…

提示工程师指南4-ChatGPT Prompt Engineering

ChatGPT Prompt Engineering 在这个部分&#xff0c;我们将介绍 ChatGPT 的最新提示工程技术&#xff0c;包括技巧、应用、限制、论文和额外的阅读材料。 主题&#xff1a; 与 ChatGPT 对话 Python 笔记本 请注意&#xff0c;本部分正在紧密开发中。 文章目录 ChatGPT Promp…

【爬虫】3.4 爬取网站复杂数据

1. Web服务器网站 进一步把前面的Web网站的mysql.html, python.html, java.html丰富其中 的内容&#xff0c;并加上图形&#xff1a; mysql.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>my…

手把手教你看懂51单片机原理图

最近当了单片机课设的助教,又再次接触了51单片机。发现初学者还看不太原理图&#xff0c;不能理解单片机 led灯&#xff0c;蜂鸣器&#xff0c;数码管是怎么操作的。现在结合原理图讲解一下怎么操作这些外设模块&#xff01;我们就以一些初始化代码进行讲解。 注&#xff1a;这…

开始使用Vue 3时应避免的10个错误

本文首发于微信公众号&#xff1a;大迁世界, 我的微信&#xff1a;qq449245884&#xff0c;我会第一时间和你分享前端行业趋势&#xff0c;学习途径等等。 更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi &#xff0c;包含一线大厂面试完整考点、资料以及我的…

华为OD机试真题 Java 实现【在字符串中找出连续最长的数字串】【2023 B卷 100分】,附详细解题思路

一、题目描述 输入一个字符串&#xff0c;返回其最长的数字子串&#xff0c;以及其长度。 若有多个最长的数字子串&#xff0c;则将它们全部输出&#xff08;按原字符串的相对位置&#xff09;。 本题含有多组样例输入。 数据范围&#xff1a; 字符串长度 1≤n≤200 &…

Linux进程懂了吗?一分钟快速上手

这里写目录标题 Linux进程介绍显示系统执行的进程终止进程查看进程树pstreeLinux进程作用 Linux进程介绍 Linux进程是计算机中正在运行的程序的实例。在Linux系统中&#xff0c;每个进程都有一个唯一的进程ID&#xff08;PID&#xff09;&#xff0c;用于标识该进程。&#xf…

Eigen中用于特征值分解的几个类的介绍

本文参考于 https://eigen.tuxfamily.org/dox/group__TopicLinearAlgebraDecompositions.html 很多场合我们需要去计算矩阵的特征值与特征向量&#xff0c;但是Eigen中有好几个计算特征值与特征向量的方法&#xff0c;这些方法到底该选哪个呢&#xff1f;这篇文章就带着大家来…

「企业技术架构」EA874:技术架构的原则和标准

企业技术架构中EA原则的应用 原则经常是正式EA工作的一部分。它们在个人决策和广泛适用且独立于具体决策的基本业务目标之间提供了更强的联系。原则是组织为激发最佳行为而选择的准则或最佳实践。它们很可能&#xff08;在最高级别&#xff09;被追溯到基本的业务需求和策略。如…

【MySQL数据库 | 第八篇】DML操作

目录 ​编辑 &#x1f914;前言&#xff1a; &#x1f914;DML介绍&#xff1a; &#x1f914;语法详情&#xff1a; &#x1f600;1.插入数据&#xff1a; 特点&#xff1a; 1.给指定字段添加数据&#xff1a; 代码示例: 运行结果&#xff1a; 2.给所有的字段添加数据&…

Symfony v6.2.11 正式发布,经典 PHP Web 开发框架

导读Symfony v6.2.11 发布了&#xff01;Symfony 是一款基于 MVC 架构的 PHP 框架&#xff0c;致力于减少重复代码的编写&#xff0c;以加速 Web 应用的开发和维护。Symfony 与许多关系型数据库集成的也非常好&#xff0c;成本也较小。 此外&#xff0c;Symfony 致力于在企业背…

继电器在信号系统中的应用

继电器是什么 继电器是一种电气开关&#xff0c;它使用电磁力来控制一个或多个电气电路的操作。继电器通常由电磁铁、触点和弹簧等部件组成。当电磁铁被激活时&#xff0c;它会产生磁场&#xff0c;吸引或释放触点&#xff0c;从而打开或关闭电路。 继电器的分类 继电器分为…

面向对象设计中的七大设计原则与二十三种设计模式

目录 七大设计原则单一职责原则内涵与目的涉及的知识点例子 开闭原则定义实现例子 依赖倒转原则定义传统过程式设计面向对象设计与开闭原则的联系例子 里氏替换原则定义与意义四层含义例子 接口隔离原则定义例子 合成复用原则定义继承复用与组合/聚合复用的区别涉及的知识点例子…

c++11 标准模板(STL)(std::bitset)(七)

定义于头文件 <bitset> template< std::size_t N > class bitset; 类模板 bitset 表示一个 N 位的固定大小序列。可以用标准逻辑运算符操作位集&#xff0c;并将它与字符串和整数相互转换。 bitset 满足可复制构造 (CopyConstructible) 及可复制赋值 (CopyAssig…

LeetCode_二叉树_BFS_中等_199.二叉树的右视图

目录 1.题目2.思路3.代码实现&#xff08;Java&#xff09; 1.题目 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1&#xff1a; 输入: [1,2,3,null,5,null,4] 输出: [1,…

测试计划包括哪些主要步骤和信息?

测试计划包括哪些主要步骤和信息? 在软件测试的过程中&#xff0c;编写一个完整的测试计划是非常重要的一步。测试计划记录了测试的具体内容、步骤、目标及其实现计划、测试环境和相关资源等信息。下面将为您详细介绍测试计划包括哪些主要步骤和信息。 1. 测试概述 测试概述部…

centos7 部署 Mysql 5.7

centos7 部署 Mysql 5.7 一、安装2.1 环境准备2.2 开始安装2.2.1 安装源2.2.2 版本选择2.2.3 安装 MySQL 二、MySQL 设置2.1 密码设置2.2 远程访问账户设置2.3 设置开机启动 一、安装 2.1 环境准备 1、查看系统自带或之前安装的 mariadb。 rpm -qa | grep mariadb2、卸载它们…

Nginx+Tomcat实现负载均衡、动静分离集群部署

NginxTomcat实现负载均衡、动静分离集群部署 一、Tomcat多实例部署1、安装好JDK2、安装tomcat3、配置tomcat环境变量4、修改tomcat2中的server.xml文件&#xff0c;要求各tomcat实例配置不能有重复的端口号5、修改各tomcat实例中的startup.sh和shutdown.sh文件&#xff0c;添加…

ArrayList 万字长文解析:使用、优化、源码分析

文章目录 ArrayList 万字长文解析&#xff1a;使用、优化、源码分析前言ArrayList 简介ArrayList 的基本使用方法ArrayList 性能优化ArrayList 的源码分析内部结构构造方法解析扩容机制System.arraycop与 Arrays.copyof 实现方式 与 使用场景迭代器 JDK 8版本 ArrayList bug 示…