怒刷LeetCode的第19天(Java版)

目录

第一题

题目来源

题目内容

解决方法

方法一:遍历一次数组

方法二:贪心算法

方法三:双指针

第二题

题目来源

题目内容

解决方法

方法一:动态规划

方法二:贪婪算法

方法三:正则表达式

第三题

题目来源

题目内容

解决方法

方法一:贪心算法

方法二:动态规划

方法三:广度优先搜索

方法四:逆向贪婪算法



第一题

题目来源

605. 种花问题 - 力扣(LeetCode)

题目内容

解决方法

方法一:遍历一次数组

该问题的思路与算法如下:

  1. 初始化一个计数器count为0,用于记录可以种植花的数量。
  2. 遍历花坛数组,检查每个位置是否可以种植花。
    • 如果当前位置为0,且其相邻的两个位置也为0(或者是边界情况),则该位置可以种植花。将该位置设为1,计数器count加1。
  3. 遍历结束后,判断计数器count的值是否大于等于n。
    • 如果是,则表示可以种入n朵花,返回true。
    • 如果不是,则表示不能种入n朵花,返回false。

这个思路的关键在于遍历花坛数组,检查每个位置是否满足种植花的条件。需要注意边界情况的处理,即第一个位置和最后一个位置的相邻位置的判断条件略有不同。通过遍历一次数组,可以快速判断能否种入n朵花。时间复杂度为O(n),其中n为花坛数组的长度。

class Solution {
public static boolean canPlaceFlowers(int[] flowerbed, int n) {int count = 0;int length = flowerbed.length;int i = 0;while (i < length) {if (flowerbed[i] == 0 && (i == 0 || flowerbed[i - 1] == 0) && (i == length - 1 || flowerbed[i + 1] == 0)) {flowerbed[i] = 1;count++;}i++;if (count >= n) {return true;}}return false;}
}

复杂度分析:

  • 时间复杂度:遍历一次花坛数组,对于每个位置最多访问其相邻的两个位置,因此时间复杂度为O(n),其中n为花坛数组的长度。
  • 空间复杂度:该算法只使用了常数个变量,因此空间复杂度为O(1)。

综上所述,该算法的时间复杂度为O(n),空间复杂度为O(1)。

LeetCode运行结果:

方法二:贪心算法

除了遍历数组的解法,还可以使用贪心算法来解决这个问题。具体思路是:从左到右遍历花坛数组,如果当前位置为0且其相邻的左右位置都是0,则在该位置种植花,并将计数器加1;如果当前位置为1,则直接跳到下一个位置。

使用贪心算法的好处在于避免了对整个数组的遍历,而是仅仅关注每个位置是否能够种植花。这样可以优化时间复杂度,使得算法的运行时间更快。

class Solution {
public static boolean canPlaceFlowers(int[] flowerbed, int n) {int count = 0;int i = 0;while (i < flowerbed.length) {if (flowerbed[i] == 0 && (i == 0 || flowerbed[i - 1] == 0) && (i == flowerbed.length - 1 || flowerbed[i + 1] == 0)) {flowerbed[i] = 1;count++;}i++;}return count >= n;}
}

复杂度分析:

  • 时间复杂度: 这个解法只需要遍历一次花坛数组,对于每个位置最多访问其相邻的两个位置。因此,时间复杂度为 O(n),其中 n 是花坛数组的长度。
  • 空间复杂度: 该解法只使用了常数个变量,所以空间复杂度为 O(1)。

综上所述,使用贪心算法的解法的时间复杂度为 O(n),空间复杂度为 O(1)。与遍历数组的解法相比,在时间复杂度上并无区别,但是在代码实现上更简洁。

LeetCode运行结果:

方法三:双指针

除了遍历数组、贪心算法,还可以使用双指针来解决这个问题。

具体思路是使用两个指针,一个指向当前位置,一个指向前一个位置。从左到右遍历花坛数组,如果当前位置为0且前一个位置和后一个位置都是0,则在该位置种植花,并将计数器加1。然后将两个指针向后移动两位,继续遍历下一个位置。

class Solution {
public static boolean canPlaceFlowers(int[] flowerbed, int n) {int count = 0;int i = 0;while (i < flowerbed.length) {if (flowerbed[i] == 0 && (i == 0 || flowerbed[i - 1] == 0) && (i == flowerbed.length - 1 || flowerbed[i + 1] == 0)) {flowerbed[i] = 1;count++;i += 2;} else {i++;}}return count >= n;}
}

复杂度分析:

  • 时间复杂度:O(n),其中n为花坛数组的长度。
  • 空间复杂度:O(1),只需要常数级别的额外空间存储临时变量。

与贪心算法相比,在思路上稍微有所不同,但在时间复杂度和空间复杂度上相同。

LeetCode运行结果:

第二题

题目来源

44. 通配符匹配 - 力扣(LeetCode)

题目内容

解决方法

方法一:动态规划

这个问题可以使用动态规划的思路来解决。

我们可以定义一个二维布尔数组dp,其中dp[i][j]表示字符串s的前i个字符和模式串p的前j个字符是否匹配。

接下来我们分析状态转移的情况:

  1. 当s的第i个字符和p的第j个字符相等或者p的第j个字符为'?'时,dp[i][j]的值取决于dp[i-1][j-1],即s的前i-1个字符和p的前j-1个字符是否匹配。
  2. 当p的第j个字符为'*'时,dp[i][j]的值可以从dp[i][j-1]或dp[i-1][j]转移而来:
    • dp[i][j-1]表示'*'匹配了空字符,此时dp[i][j]的值取决于dp[i][j-1];
    • dp[i-1][j]表示'*'匹配了s的第i个字符,此时dp[i][j]的值取决于dp[i-1][j]。

根据以上分析,我们可以得到动态规划的状态转移方程:

if (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '?') {dp[i][j] = dp[i - 1][j - 1];
} else if (p.charAt(j - 1) == '*') {dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
}

边界情况:

  • dp[0][0]表示空字符和空字符完全匹配,初始化为true;
  • dp[0][j]表示空字符和模式串p的前j个字符匹配的情况。若p的第j个字符为'*',则dp[0][j]的值取决于dp[0][j-1];否则为false;
  • dp[i][0]表示字符串s的前i个字符和空字符匹配的情况,都为false。

最终,我们返回dp[m][n],即字符串s的全部字符和模式串p的全部字符是否完全匹配。

class Solution {public boolean isMatch(String s, String p) {int m = s.length(), n = p.length();boolean[][] dp = new boolean[m + 1][n + 1];dp[0][0] = true;// 处理 p 以 * 开头的情况for (int j = 1; j <= n; j++) {if (p.charAt(j - 1) == '*') {dp[0][j] = true;} else {break;}}for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {if (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '?') {dp[i][j] = dp[i - 1][j - 1];} else if (p.charAt(j - 1) == '*') {dp[i][j] = dp[i][j - 1] || dp[i - 1][j];}}}return dp[m][n];}
}

复杂度分析:

对于给定长度为m的字符串s和长度为n的模式串p,动态规划解法的时间复杂度为O(mn),空间复杂度也为O(mn)。

在计算过程中,我们需要填充一个大小为(m+1)×(n+1)的二维dp数组。每个位置的填充操作需要常数时间,因此总的时间复杂度为O(m*n)。

同时,我们只使用一个二维dp数组来存储中间结果,所以空间复杂度也是O(m*n)。

需要注意的是,这里的m和n并不是指s和p的最大长度,而是分别表示s和p实际的长度加1。这是因为我们在填充dp数组时,需要考虑到空字符和空模式串的情况。

总结起来,该解法具有较优的时间和空间复杂度,适用于处理规模较小的字符串匹配问题。

LeetCode运行结果:

方法二:贪婪算法

除了动态规划,还可以使用贪婪算法进行字符串匹配。贪婪算法通常是一种基于局部最优选择的策略,在某些情况下可以得到快速且有效的解。具体到字符串匹配问题,我们可以通过迭代遍历的方式来实现贪婪算法。

该贪婪算法的思路是一次处理字符串s和模式串p的一个字符,根据当前的字符匹配情况进行不同操作:

  • 若两个字符相等或者模式串p的当前字符为'?',则两个索引都向后移动;
  • 若模式串p的当前字符为'*',记录当前位置,并只移动模式串的索引;
  • 若当前字符不匹配,但之前出现过''的情况,回溯到''匹配的下一个位置,并将字符串索引+1;
  • 若没有之前出现过'*'的情况,则匹配失败。
  • 最后需要处理模式串p末尾的多余字符,判断是否全部为'*'。

该贪婪算法在某些情况下可以得到快速的解,但并不适用于所有的字符串匹配问题。在一些特殊的模式串情况下,可能会导致错误的匹配结果。因此,在实际应用中,需要根据具体情况选择合适的解法。

class Solution {public boolean isMatch(String s, String p) {int sIndex = 0; // 字符串s的索引int pIndex = 0; // 模式串p的索引int matchIndex = -1; // 最近一次出现'*'匹配的位置int starIndex = -1; // 最近一次出现'*'的位置while (sIndex < s.length()) {// 当两个字符相等或模式串为'?'时,两个索引都向后移动if (pIndex < p.length() && (s.charAt(sIndex) == p.charAt(pIndex) || p.charAt(pIndex) == '?')) {sIndex++;pIndex++;}// 当模式串为'*'时,记录当前位置,并只移动模式串的索引else if (pIndex < p.length() && p.charAt(pIndex) == '*') {starIndex = pIndex;matchIndex = sIndex;pIndex++;}// 当前字符不匹配,但有之前出现过'*'的情况,回溯到'*'匹配的下一个位置,并将字符串索引+1else if (starIndex != -1) {pIndex = starIndex + 1;matchIndex++;sIndex = matchIndex;}// 当没有之前出现过'*'的情况,返回falseelse {return false;}}// 处理模式串末尾的多余字符while (pIndex < p.length() && p.charAt(pIndex) == '*') {pIndex++;}// 字符串s和模式串p都遍历完毕,则匹配成功return pIndex == p.length();}
}

复杂度分析:

设字符串 s 的长度为 n,模式串 p 的长度为 m。

  • 在最坏情况下(即没有匹配的字符和通配符时),两个索引 sIndex 和 pIndex 都要遍历整个字符串 s 和模式串 p。 时间复杂度为 O(n+m)。
  • 在处理通配符 '*' 时,如果出现回溯的情况,需要在每次回溯时移动 pIndex 和 matchIndex,直到找到匹配的字符位置。 由于每次回溯都会移动 sIndex,所以总共只会有 n 次回溯操作。 因此,在最坏情况下,回溯操作的时间复杂度为 O(n)。
  • 在处理模式串末尾的多余字符时,需要遍历剩余的模式串字符。 时间复杂度为 O(m-pIndex)。

综上所述,代码的总体时间复杂度为 O(n+m),空间复杂度为 O(1)。

LeetCode运行结果:

方法三:正则表达式
class Solution {public boolean isMatch(String s, String p) {String regex = p.replace("?", ".").replace("*", ".*");return s.matches(regex);}
}

这个实现使用了 Java 的正则表达式来处理通配符匹配。首先,将模式串 p 中的 '?' 替换成 '.',将 '' 替换成 '.',得到一个新的正则表达式 regex。

然后,使用字符串 s 的 matches() 方法,测试字符串 s 是否能够匹配正则表达式 regex。如果能够匹配,则返回 true,否则返回 false。

需要注意的是,该方法只是一种简单的通配符匹配算法,可能无法处理一些复杂的情况。在实际应用中,需要根据需求选择更加高效和精确的算法。

复杂度分析:

  • 时间复杂度分析:使用正则表达式的 matches() 方法进行匹配,具体的实现和性能取决于底层正则引擎。一般情况下,时间复杂度为 O(M*N),其中 M 是模式串 p 的长度,N 是字符串 s 的长度。
  • 空间复杂度分析:空间复杂度取决于正则表达式的匹配过程中是否需要生成匹配结果的存储。在 Java 的 matches() 方法中,会将整个匹配结果存储在内存中,并返回一个 boolean 值表示是否匹配成功。因此,空间复杂度为 O(M*N),其中 M 是模式串 p 的长度,N 是字符串 s 的长度。

LeetCode运行结果:

第三题

题目来源

45. 跳跃游戏 II - 力扣(LeetCode)

题目内容

解决方法

方法一:贪心算法
class Solution {public int jump(int[] nums) {if (nums.length <= 1) {return 0;}int maxReach = nums[0]; // 当前能够到达的最远位置int steps = nums[0]; // 当前步数内能够到达的最远位置int jumps = 1; // 跳跃次数for (int i = 1; i < nums.length; i++) {// 如果当前位置超过了最远位置,需要进行一次跳跃if (i > maxReach) {jumps++;maxReach = steps;}// 更新当前步数内能够到达的最远位置steps = Math.max(steps, i + nums[i]);}return jumps;}
}

在这个实现中,我们使用贪心算法来寻找最优解。我们定义三个变量:

  • maxReach:当前能够到达的最远位置
  • steps:当前步数内能够到达的最远位置
  • jumps:跳跃次数

我们从索引 1 开始遍历数组,每次更新 steps 的值为当前位置加上当前元素的值。如果当前位置超过了 maxReach,说明我们需要进行一次跳跃,此时将 jumps 加 1,并更新 maxReach 为 steps。

最终,返回 jumps 的值即为到达最后一个位置的最小跳跃次数。

复杂度分析:

  • 时间复杂度是 O(n),其中 n 是数组 nums 的长度。这是因为我们只需要遍历一次数组,每次遍历都更新跳跃的最远位置和步数内能够到达的最远位置。
  • 空间复杂度是 O(1),即常数级别的额外空间。这是因为我们只使用了几个变量来保存最远位置、步数和跳跃次数,没有使用额外的数组或数据结构。

因此,该算法是一个高效的解决方案,可以在给定的约束条件下快速求解跳跃游戏问题。

LeetCode运行结果:

方法二:动态规划

除了贪心算法,还可以使用动态规划来解决跳跃游戏 II 问题。

class Solution {public int jump(int[] nums) {int n = nums.length;int[] dp = new int[n]; // dp[i] 表示到达第 i 个位置所需的最小跳跃次数Arrays.fill(dp, Integer.MAX_VALUE);dp[0] = 0;for (int i = 0; i < n; i++) {int maxJump = nums[i]; // 当前位置能够跳跃的最大长度for (int j = 1; j <= maxJump && i + j < n; j++) {dp[i + j] = Math.min(dp[i + j], dp[i] + 1);}}return dp[n - 1];}
}

在这个实现中,我们首先创建一个长度为 n 的数组 dp,用于保存到达每个位置所需的最小跳跃次数。初始化 dp[0] 为 0,其它位置的值都设置为一个较大的数,表示初始状态为无穷大。

然后,我们从左向右遍历数组 nums,对于每个位置 i,将当前位置能够跳跃的最大长度 nums[i] 内的所有位置的 dp 值更新为 dp[i] + 1,表示通过当前位置 i 进行一次跳跃。

最终,返回 dp[n - 1] 的值即为到达最后一个位置的最小跳跃次数。

该算法的时间复杂度是 O(n^2),其中 n 是数组 nums 的长度。因为我们需要遍历每个位置,并且对于每个位置,还需要遍历当前位置能够跳跃的最大长度内的所有位置。

复杂度分析:

  • 时间复杂度是 O(n^2),其中 n 是数组 nums 的长度。这是因为我们需要遍历每个位置,并对于每个位置,还需要遍历当前位置能够跳跃的最大长度内的所有位置。
  • 空间复杂度是 O(n),即额外使用了一个数组 dp 来保存最小跳跃次数。这是因为我们需要存储到达每个位置所需的最小跳跃次数。

虽然动态规划解法的时间复杂度较高,但它提供了一种通用的解决方法,适用于各种求解最优解问题的场景。在实际应用中,可以根据输入规模和实际需求来选择贪心算法或动态规划来解决跳跃游戏问题。如果输入规模较小,动态规划算法的性能可能会比较好;如果输入规模较大,贪心算法可能会更加高效。

LeetCode运行结果:

方法三:广度优先搜索

除了贪婪算法和动态规划之外,还有一种常见的解决方法是使用广度优先搜索(BFS)。

import java.util.LinkedList;
import java.util.Queue;class Solution {public int jump(int[] nums) {int n = nums.length;if (n == 1) {return 0; // 如果数组长度为 1,则不需要跳跃}Queue<Integer> queue = new LinkedList<>(); // 用于保存当前位置的队列boolean[] visited = new boolean[n]; // 记录每个位置是否已访问visited[0] = true;queue.offer(0); // 将起始位置加入队列int step = 0; // 跳跃的次数while (!queue.isEmpty()) {int size = queue.size();for (int i = 0; i < size; i++) {int currIndex = queue.poll();int maxJump = nums[currIndex];for (int j = 1; j <= maxJump; j++) {int nextIndex = currIndex + j;if (nextIndex >= n - 1) {// 如果能够跳到最后一个位置或超过最后一个位置,则返回当前步数+1return step + 1;}if (!visited[nextIndex]) {visited[nextIndex] = true;queue.offer(nextIndex);}}}step++;}return -1; // 如果无法达到最后一个位置,则返回 -1}
}

在这个实现中,我们使用一个队列 queue 来广度优先搜索每个位置能够跳跃到的下一个位置。

  1. 初始时,我们将起始位置加入队列,并将其标记为已访问。
  2. 然后,我们不断从队列中取出当前位置,遍历它能够跳跃的最大长度内的所有位置。如果遍历过程中发现某个位置能够跳到最后一个位置或超过最后一个位置,则返回当前步数+1,表示跳跃结束。
  3. 如果无法达到最后一个位置,则返回 -1。

复杂度分析:

时间复杂度:

  • 遍历数组的过程中,每个位置最多会被访问一次,因此遍历数组的时间复杂度是 O(n)。
  • 在最坏情况下,队列中的元素数量可以达到 n,每个元素都需要进行扩展操作。在每个扩展操作中,需要遍历当前位置能够跳跃的最大长度内的所有位置。由于最大跳跃长度的上限是 n,因此每个位置进行扩展操作的时间复杂度是 O(n)。总的时间复杂度是 O(n^2)。

空间复杂度:

  • 使用一个队列来保存当前位置,队列的最大长度不会超过 n,因此队列的空间复杂度是 O(n)。
  • 使用一个布尔数组 visited 来记录已访问的位置,数组的长度与数组 nums 的长度相同,因此布尔数组的空间复杂度也是 O(n)。
  • 总的空间复杂度是 O(n)。

需要注意的是,由于贪婪算法的效率更高,动态规划和广度优先搜索通常在处理较大输入规模时才会被使用。在小规模问题上,贪婪算法往往是更快的解决方法。

LeetCode运行结果:

方法四:逆向贪婪算法

除了贪婪算法、动态规划和广度优先搜索,还有另外一种常用的解决方法,称为跳跃游戏问题的逆向贪婪算法。

逆向贪婪算法的基本思路是从目标位置开始向起始位置遍历,每次选择能够到达当前位置的最远跳跃位置作为新的目标位置,直到遍历到起始位置为止。这样可以得到从起始位置到目标位置的最小跳跃次数。

class Solution {public int jump(int[] nums) {int position = nums.length - 1;int jumps = 0;while (position > 0) {for (int i = 0; i < position; i++) {if (i + nums[i] >= position) {position = i;jumps++;break;}}}return jumps;}
}

在这个实现中,我们使用变量 position 来表示当前的目标位置,初始化为数组的最后一个位置。变量 jumps 记录跳跃次数,初始化为 0。

通过一个循环,我们从目标位置开始向起始位置遍历。内层循环遍历从当前位置到目标位置之间的所有位置,找到第一个能够跳跃到目标位置的位置,更新 position 和 jumps,然后继续向前遍历。

最终,返回 jumps 作为结果。

复杂度分析:

时间复杂度:

  • 遍历数组进行内层循环时,最多需要执行 n 次,其中 n 是数组 nums 的长度。因此,内层循环的时间复杂度是 O(n)。
  • 外层循环从目标位置开始,通过不断更新目标位置进行遍历,最多执行 n-1 次。因此,外层循环的时间复杂度是 O(n)。 综合起来,逆向贪婪算法的时间复杂度是 O(n)。

空间复杂度:

  • 逆向贪婪算法只使用了常数级别的变量,没有使用额外的空间。因此,空间复杂度是 O(1)。

总结起来,逆向贪婪算法是一种时间复杂度为 O(n),空间复杂度为 O(1) 的解决方法。相比于动态规划和广度优先搜索等其他方法,它具有更低的时间复杂度,但需要注意的是,逆向贪婪算法的前提是能够到达目标位置,否则会陷入无限循环。

LeetCode运行结果:

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

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

相关文章

玄子Share 设计模式 GOF 全23种 + 七大设计原则

玄子Share 设计模式 GOF 全23种 七大设计原则 前言&#xff1a; 此文主要内容为 面向对象七大设计原则&#xff08;OOD Principle&#xff09;GOF&#xff08;Gang Of Four&#xff09;23种设计模式拓展的两个设计模式 简单工厂模式&#xff08;Simple Factory Pattern&#x…

基于Java实现的仓库管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言功能介绍&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导…

解密PDF密码

PDF文件有两种密码&#xff0c;一个打开密码、一个限制编辑密码&#xff0c;因为PDF文件设置了密码&#xff0c;那么打开、编辑PDF文件就会受到限制。忘记了PDF密码该如何解密&#xff1f; PDF和office一样&#xff0c;可以对文件进行加密&#xff0c;但是没有提供恢复密码的功…

智能驾驶、智能家居、智能工业中的 AI 关键基础设施,半导体厂商恩智浦的角色是什么?

我们来看一条七年前的真实新闻报道&#xff0c;2016 年《福布斯》在报道中提到“2020 年会有 1000 万台的自动驾驶汽车”。然而 2023 年的现在&#xff0c;真正实现 L4 级别自动驾驶的汽车&#xff0c;仍然远远没有达到这个预测的数量。 另一边&#xff0c;数据显示&#xff0c…

【数据结构】排序算法(一)—>插入排序、希尔排序、选择排序、堆排序

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.直接插入排序 2.希尔排序 3.直接选择排…

使用不同尺寸的传感器拍照时,怎么保证拍出同样视场范围的照片?

1、问题背景 使用竞品机做图像效果对比时&#xff0c;我们通常都会要求拍摄的照片要视场范围一致&#xff0c;这样才具有可比性。之前我会考虑用同样焦距、同样分辨率的设备去拍照对比就可以了&#xff0c;觉得相机的视场范围只由镜头焦距来决定。 但如果对于不同尺寸的传感器…

使用 Matter-SDK 快速搭建 Matter 环境 (Linux)

Matter 作为一个统一的智能家居互联协议&#xff0c;凭借其高兼容性的特点&#xff0c;正逐渐打破各个智能家居之间的壁垒。乐鑫作为在 Matter 项目发布之初的早期成员&#xff0c;提供了一套开源、完整、易用的 Matter-SDK。 乐鑫的 Matter-SDK 是建立在开源 Matter-SDK 之上…

IOTE 2023盛况回顾,美格智能聚连接之力促数字新生长

9月20~22日&#xff0c;IOTE国际物联网展深圳站在深圳国际会展中心正式召开。本届展会以“IoT构建数字经济底座”为主题&#xff0c;聚焦物联网技术助推数字经济发展的核心动力。美格智能携前沿技术成果亮相展会&#xff0c;与参展观众深入交流。 展会上&#xff0c;美格智能带…

大型企业网如何部署NAT实现需求

1.企业中堕胎电脑如何共享上网&#xff1f; 2.NAT地址转换原理讲解&#xff1b; 3.企业机房如何用NAT让服务器更安全&#xff1f; - NAT - 网络地址转换 - 什么式网络地址 IP地址 -通信时候的设备标识 - 为什么要把IP地址做转换呢&#xff1f; -- 公网IP&#xff…

什么是推挽电路?

推挽电路原理&#xff1a; 可以简单理解为推和拉&#xff1b; 此电路总共用到两个元器件&#xff0c;对应图中的Q1----NPN三极管&#xff0c;Q2----PNP三极管&#xff0c;两个电阻R1和R2起到限流的作用&#xff1b;两个三极管的中间对应信号的输出。 下面就举例说明是如何工作的…

【计算机网络】图解路由器(一)

本系列包含&#xff1a; 图解路由器&#xff08;一&#xff09;图解路由器&#xff08;二&#xff09; 图解路由器&#xff08;一&#xff09; 1、什么是路由器&#xff1f;2、什么是路由选择&#xff1f;3、什么是转发&#xff1f;4、路由器设备有哪些类型&#xff1f;5、根据…

Redis原理(二):Redis数据结构(下)

文章目录 1.7 Redis数据结构-SkipList1.7 Redis数据结构-RedisObject1.8 Redis数据结构-String1.9 Redis数据结构-List2.0 Redis数据结构-Set结构2.1、Redis数据结构-ZSET2.2 、Redis数据结构-Hash1.7 Redis数据结构-SkipList SkipList(跳表)首先是链表,但与传统链表相比有…

day09_数组进阶

今日内容 零、 复习昨日 一、作业 二、引用类型[重要] 三、数组拷贝 四、数组扩容 五、数组排序[面试|笔试] 六、Arrays 零、 复习昨日 1数组创建后能否改变长度 不能 2数组创建后能否存储不同类型的数据 不能 √能,能默认转型的可以存储 double[] arr2 new double[3]; arr2[0…

数据库选型参考

文章目录 前言嵌入式数据库数据库服务器PostgreSQL和MySQL的对比 NoSQL国产数据库阿里PolarDB腾讯TDSQL阿里OceanBase和PolarDB的区别 华为GaussDb 前言 DB-Engines Ranking 会根据受欢迎程度对数据库管理系统进行排名&#xff0c;排名每月更新一次。 分为关系型数据库、Key-V…

UML基础与应用之面向对象

UML&#xff08;Unified Modeling Language&#xff09;是一种用于软件系统建模的标准化语言&#xff0c;它使用图形符号和文本来描述软件系统的结构、行为和交互。在面向对象编程中&#xff0c;UML被广泛应用于软件系统的设计和分析阶段。本文将总结UML基础与应用之面向对象的…

广告牌安全监测系统,用科技护航大型广告牌安全

城市的街头巷尾&#xff0c;处处可见高耸的广告牌&#xff0c;它们以各种形式和颜色吸引着行人的目光。然而&#xff0c;作为城市景观的一部分&#xff0c;广告牌的安全性常常被我们所忽视。广告牌量大面大&#xff0c;由于设计、材料、施工方法的缺陷&#xff0c;加上后期的检…

队列的使用以及模拟实现(C++版本)

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;强烈推荐优质专栏: &#x1f354;&#x1f35f;&#x1f32f;C的世界(持续更新中) &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;…

npm ,yarn 更换使用国内镜像源,淘宝源

背景 文章首发地址 在平时开发当中&#xff0c;我们经常会使用 Npm&#xff0c;yarn 来构建 web 项目。但是npm默认的源的服务器是在国外的&#xff0c;如果没有梯子的话。下载速度会特别慢。那有没有方法解决呢&#xff1f; 其实是有的&#xff0c;设置国内镜像即可&#x…

39 | selenium基础架构,UI测试架构

什么是测试基础架构&#xff1f; 测试基础架构指的是&#xff0c;执行测试的过程中用到的所有基础硬件设施以及相关的软件设施。因此&#xff0c;我们也把测试基础架构称之为广义的测试执行环境。通常来讲&#xff0c;测试基础架构主要包括以下内容&#xff1a; 执行测试的机器…

2023-9-28 JZ26 树的子结构

题目链接&#xff1a;树的子结构 import java.util.*; /** public class TreeNode {int val 0;TreeNode left null;TreeNode right null;public TreeNode(int val) {this.val val;}} */ public class Solution {public boolean HasSubtree(TreeNode root1,TreeNode root2) …