【优选算法篇】在分割中追寻秩序:二分查找的智慧轨迹

文章目录

  • C++ 二分查找详解:基础题解与思维分析
    • 前言
    • 第一章:热身练习
      • 1.1 二分查找基本实现
        • 解题思路
        • 图解分析
        • C++代码实现
        • 易错点提示
        • 代码解读
      • 1.2 在排序数组中查找元素的第一个和最后一个位置
        • 解题思路
        • 1.2.1 查找左边界
          • 算法步骤:
          • 图解分析
          • C++代码实现
        • 1.2.2 查找右边界
          • 算法步骤:
          • 图解分析
          • C++代码实现
        • 1.2.3 组合查找结果
          • C++完整代码
      • 1.3 搜索插入位置
        • 解题思路
        • 1.3.1 二分查找算法分析
          • 算法步骤:
          • 图解分析
          • C++代码实现
          • 易错点提示
          • 代码解读
      • 1.4 x 的平方根
          • 解题思路
        • 1.4.1 暴力查找
          • 算法步骤:
          • C++代码实现
          • 图解分析
        • 1.4.2 二分查找法
          • 算法步骤:
          • 图解分析
          • C++代码实现
          • 易错点提示
          • 代码解读
    • 写在最后
      • 二分查找算法总结
      • 重要的三点:
      • 模板记忆技巧
      • 两段式的特殊处理:

C++ 二分查找详解:基础题解与思维分析

💬 欢迎讨论:如有疑问或见解,欢迎在评论区留言互动。

👍 点赞、收藏与分享:如觉得这篇文章对您有帮助,请点赞、收藏并分享!
🚀 分享给更多人:欢迎分享给更多对 C++ 感兴趣的朋友,一起学习二分查找的基础与进阶!


前言

二分查找法是经典的搜索算法之一,能够在有序数组中快速查找目标元素。它的时间复杂度为 O(log n),相比于线性搜索有着更高的效率。本篇博客将详细分析二分查找的原理,并结合题目讲解,帮助大家全面掌握这一重要的算法技巧。


第一章:热身练习

1.1 二分查找基本实现

题目链接:704. 二分查找

题目描述

给定一个升序排列的整数数组 nums,和一个目标值 target。如果 target 在数组中存在,返回其下标;否则,返回 -1

示例 1

  • 输入:nums = [-1,0,3,5,9,12], target = 9
  • 输出:4
  • 解释:9 出现在 nums 中,并且下标为 4

示例 2

  • 输入:nums = [-1,0,3,5,9,12], target = 2
  • 输出:-1
  • 解释:2 不存在 nums 中,因此返回 -1

提示

  • 你可以假设数组中的所有元素是互不相同的。
  • 数组 nums 的长度范围为 [1, 10000]
  • 数组 nums 的每个元素都在 [-9999, 9999] 之间。

解题思路

二分查找的核心思想是利用数组的有序性,通过每次将查找范围缩小一半来快速锁定目标位置。我们在数组的中间位置进行比较,根据比较结果判断应该继续在左侧还是右侧进行查找。

具体思路如下:

  1. 初始化左右指针

    • left 指向数组的起始位置。
    • right 指向数组的末尾位置。
  2. 计算中间位置

    • 通过公式 mid = left + (right - left) / 2 来计算中间位置 mid这个公式可以避免直接相加 left + right 可能导致的整数溢出。
  3. 比较中间元素与目标值

    • 如果 nums[mid] == target,则直接返回 mid
    • 如果 nums[mid] > target,说明目标值在左半部分,此时应将 right 更新为 mid - 1
    • 如果 nums[mid] < target,说明目标值在右半部分,此时应将 left 更新为 mid + 1
  4. 结束条件

    • left > right 时,说明查找范围为空,目标值不存在,返回 -1

图解分析

假设数组 nums = [-1, 0, 3, 5, 9, 12],目标值 target = 9。我们从数组的中间位置开始查找:

  1. 初始状态

    • left = 0right = 5
    • 中间位置 mid = (0 + 5) / 2 = 2nums[mid] = 3
    • 因为 3 < 9,所以更新 left = mid + 1 = 3
  2. 步骤 1

    • left = 3right = 5
    • 中间位置 mid = (3 + 5) / 2 = 4nums[mid] = 9
    • 找到目标值 9,返回下标 4

步骤图解

Iterationleft Pointerright Pointermid PointerArray State
1052[-1, 0, 3, 5, 9, 12]
2354[5, 9, 12]

C++代码实现
class Solution {
public:int search(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while (left <= right) {// 计算中间位置,防止溢出int mid = left + (right - left) / 2;if (nums[mid] == target) {return mid; // 找到目标,返回下标} else if (nums[mid] > target) {right = mid - 1; // 缩小查找范围至左半部分} else {left = mid + 1;  // 缩小查找范围至右半部分}}return -1; // 未找到目标,返回 -1}
};

易错点提示
  1. 防止溢出:计算中间位置时,建议使用 mid = left + (right - left) / 2,而不是 mid = (left + right) / 2,这样可以避免 left + right 直接相加时可能的整数溢出问题。
  2. 循环条件while (left <= right),当 leftright 指向相同元素时,仍然需要继续判断,因此需要取等号。
  3. 边界条件处理:如果目标值不存在于数组中,应返回 -1,避免返回无效的数组下标。

代码解读
  • 时间复杂度:每次查找都会将查找范围缩小一半,因此时间复杂度为 O(log n)
  • 空间复杂度:该算法仅使用了少量额外的变量,空间复杂度为 O(1)

1.2 在排序数组中查找元素的第一个和最后一个位置

题目链接:34. 在排序数组中查找元素的第一个和最后一个位置

题目描述

给定一个按非递减顺序排列的整数数组 nums,和一个目标值 target,请找出给定目标值在数组中的开始位置结束位置

如果数组中不存在目标值 target,返回 [-1, -1]

示例 1

  • 输入:nums = [5,7,7,8,8,10], target = 8
  • 输出:[3, 4]
  • 解释:目标值 8 在数组中的起始位置为下标 3,结束位置为下标 4

示例 2

  • 输入:nums = [5,7,7,8,8,10], target = 6
  • 输出:[-1, -1]
  • 解释:目标值 6 不存在于数组中,因此返回 [-1, -1]

示例 3

  • 输入:nums = [], target = 0
  • 输出:[-1, -1]
  • 解释:空数组中没有任何目标值,因此返回 [-1, -1]

提示

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组。
  • -109 <= target <= 109

解题思路

我们需要在时间复杂度 O(log n) 内找到目标值的起始位置结束位置,这意味着必须使用二分查找来解决问题。

基本思路:通过两次二分查找,分别找到目标值的左边界和右边界。

  1. 左边界:找到数组中第一个等于目标值的位置。
  2. 右边界:找到数组中最后一个等于目标值的位置。

接下来分别介绍如何查找这两个边界。


1.2.1 查找左边界

我们首先使用二分查找来确定目标值的起始位置,即左边界。

算法步骤:
  1. 初始化左右指针

    • left 指向数组的起始位置,right 指向数组的末尾位置。
  2. 进行二分查找

    • 计算中间位置 mid = left + (right - left) / 2
    • 如果 nums[mid] 小于目标值 target,则说明目标值在右边,因此更新 left = mid + 1
    • 如果 nums[mid] 大于或等于目标值,说明目标值在左边(包括 mid 位置),因此更新 right = mid
  3. 结束条件:当 left == right 时,查找结束。此时需要检查 nums[left] 是否等于目标值,如果相等,返回该位置;否则返回 -1


图解分析

假设数组为 nums = [5,7,7,8,8,10],目标值为 target = 8。我们从数组的中间位置开始查找:

  1. 初始状态

    • left = 0, right = 5
    • 计算中间位置 mid = (0 + 5) / 2 = 2,此时 nums[mid] = 7
    • 因为 7 < 8,所以更新 left = mid + 1 = 3
  2. 步骤 1

    • left = 3, right = 5
    • 计算中间位置 mid = (3 + 5) / 2 = 4,此时 nums[mid] = 8
    • 因为 nums[mid] >= 8,所以更新 right = mid = 4
  3. 步骤 2

    • left = 3, right = 4
    • 计算中间位置 mid = (3 + 4) / 2 = 3,此时 nums[mid] = 8
    • 因为 nums[mid] >= 8,所以更新 right = mid = 3
  4. 结束状态

    • 此时 left == right == 3,我们检查 nums[left] == 8,因此找到了目标值的起始位置 3

C++代码实现
class Solution {
public:int searchLeft(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;} else {right = mid;  // 保持目标值在左半部分}}if (nums.size() == 0 || nums[left] != target) return -1;  // 边界条件检查return left;}
};

1.2.2 查找右边界

接下来,我们使用二分查找找到目标值的结束位置,即右边界。

算法步骤:
  1. 初始化左右指针

    • left 指向数组的起始位置,right 指向数组的末尾位置。
  2. 进行二分查找

    • 计算中间位置 mid = left + (right - left + 1) / 2(向上取整)。
    • 如果 nums[mid] 小于等于目标值 target,则更新 left = mid
    • 如果 nums[mid] 大于目标值,说明目标值在左边,因此更新 right = mid - 1
  3. 结束条件:当 left == right 时,查找结束,此时 left 指向目标值的结束位置。


图解分析

假设数组为 nums = [5,7,7,8,8,10],目标值为 target = 8。我们从中间位置开始查找结束位置:

  1. 初始状态

    • left = 0, right = 5
    • 计算 mid = (0 + 5 + 1) / 2 = 3,此时 nums[mid] = 8
    • 因为 nums[mid] <= 8,所以更新 left = mid = 3
  2. 步骤 1

    • left = 3, right = 5
    • 计算 mid = (3 + 5 + 1) / 2 = 4,此时 nums[mid] = 8
    • 因为 nums[mid] <= 8,所以更新 left = mid = 4
  3. 步骤 2

    • left = 4, right = 5
    • 计算 mid = (4 + 5 + 1) / 2 = 5,此时 nums[mid] = 10
    • 因为 nums[mid] > 8,所以更新 right = mid - 1 = 4
  4. 结束状态

    • 此时 left == right == 4,因此找到了目标值的结束位置 4

C++代码实现
class Solution {
public:int searchRight(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while (left < right) {int mid = left + (right - left + 1) / 2;  // 向上取整,防止死循环if (nums[mid] <= target) {left = mid;} else {right = mid - 1;}}return left;  // 此时 left 指向最后一个目标值的位置}
};

1.2.3 组合查找结果

最后,我们将左边界和右边界的查找结果组合起来。如果左边

界的查找结果为 -1,则说明目标值不存在,返回 [-1, -1]。否则,返回 [left, right]

C++完整代码
class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {int left = searchLeft(nums, target);if (left == -1) return {-1, -1};  // 目标值不存在int right = searchRight(nums, target);return {left, right};  // 返回目标值的起始和结束位置}
};

1.3 搜索插入位置

题目链接:35. 搜索插入位置

题目描述

给定一个排序数组 nums 和一个目标值 target,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你必须设计并实现时间复杂度为 O(log n) 的算法。

示例 1

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

示例 2

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

示例 3

  • 输入:nums = [1,3,5,6], target = 7
  • 输出:4

提示:

  • 1 <= nums.length <= 104
  • 104 <= nums[i] <= 104
  • nums 为 无重复元素 的 升序 排列数组
  • 104 <= target <= 104

解题思路

该题的要求是以 O(log n) 的时间复杂度找到目标值或者其应该插入的位置,因此我们必须使用二分查找。通过二分查找,我们可以在每次查找中将搜索范围缩小一半,进而快速锁定目标值的位置,或者它应插入的准确位置。


1.3.1 二分查找算法分析

在这道题中,我们通过二分查找来确定目标值的位置。如果目标值存在,直接返回其索引;如果不存在,我们可以通过查找过程中的边界情况确定它的插入位置。

算法步骤:
  1. 初始化左右指针

    • left 指向数组的起始位置,right 指向数组的末尾位置。
  2. 进行二分查找

    • 计算中间位置 mid = left + (right - left) / 2
    • 如果 nums[mid] 小于目标值 target,则目标值可能出现在右边部分,因此更新 left = mid + 1
    • 如果 nums[mid] 大于或等于目标值,说明目标值可能在左边部分,因此更新 right = mid
  3. 结束条件:当 left == right 时,查找结束。此时的 leftright 所在的位置就是目标值应插入的位置。


图解分析

假设数组为 nums = [1,3,5,6],目标值 target = 5。我们从数组的中间位置开始查找目标值的位置或插入位置:

  1. 初始状态

    • left = 0right = 3
    • 计算中间位置 mid = (0 + 3) / 2 = 1,此时 nums[mid] = 3
    • 因为 3 < 5,更新 left = mid + 1 = 2
  2. 步骤 1

    • left = 2right = 3
    • 计算中间位置 mid = (2 + 3) / 2 = 2,此时 nums[mid] = 5
    • 因为 nums[mid] == 5,找到目标值,返回下标 2
  3. 插入位置场景

    • 如果 target = 2,则当 left = 0right = 1 时,nums[mid] = 1,更新 left = 1,最后返回 1 作为插入位置。

步骤图解

Iterationleft Pointerright Pointermid PointerArray State
1031[1, 3, 5, 6]
2232[5, 6]

C++代码实现
class Solution {
public:int searchInsert(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;} else {right = mid;  // 缩小查找范围至左半部分}}// 最终结果在 left 或 right 位置if (nums[left] < target) return left + 1;return left;}
};

易错点提示
  1. 二分查找的边界条件:要确保循环结束条件是 left == right,这意味着在查找结束后,leftright 位置就是插入点。
  2. 处理插入位置的返回值:当 nums[left] 小于 target 时,表示目标值应插入到 left + 1 的位置,否则插入到 left 位置。

代码解读
  • 时间复杂度:每次查找都会将查找范围缩小一半,因此时间复杂度为 O(log n)
  • 空间复杂度:该算法仅使用了少量的额外变量,空间复杂度为 O(1)

1.4 x 的平方根

题目链接:69. x 的平方根

题目描述

给定一个非负整数 x,计算并返回 x算术平方根。由于返回类型是整数,结果只保留整数部分,小数部分将被舍去

注意不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5

示例 1

  • 输入:x = 4
  • 输出:2

示例 2

  • 输入:x = 8
  • 输出:2
  • 解释:8 的算术平方根是 2.82842...,由于返回类型是整数,小数部分将被舍去。

提示:

  • 0 <= x <= 2^31 - 1

解题思路

我们可以通过暴力查找和二分查找两种方法来解决该问题。

暴力查找方法简单直接,逐个枚举可能的平方根,直到找到符合条件的数为止。
二分查找方法则更加高效,利用有序性质通过缩小区间的方式快速锁定平方根。

接下来我们分别详细介绍这两种方法。


1.4.1 暴力查找

暴力查找法的核心思想是从 0 开始枚举所有可能的平方根 i,依次判断 i * i 是否等于或超过目标值 x。一旦找到符合条件的 i,就可以直接返回结果。

算法步骤:
  1. 遍历所有可能的数:从 i = 0 开始,逐一检查 i * i 是否等于 x 或者超过 x
  2. 判断条件
    • 如果 i * i == x,说明找到了平方根,直接返回 i
    • 如果 i * i > x,说明 i 已经超出目标值的平方,返回前一个数 i - 1 作为平方根。
C++代码实现
class Solution {
public:int mySqrt(int x) {// 由于两个较大的数相乘可能会超过 int 最大范围,因此用 long longlong long i = 0;for (i = 0; i <= x; i++) {// 如果两个数相乘正好等于 x,直接返回 iif (i * i == x) return i;// 如果第一次出现两个数相乘大于 x,说明结果是前一个数if (i * i > x) return i - 1;}// 处理边界情况return -1;}
};

图解分析

假设 x = 8,我们逐个枚举所有可能的平方根:

  1. 初始状态
    • i = 0i * i = 0,继续下一次循环。
  2. 步骤 1
    • i = 1i * i = 1,继续下一次循环。
  3. 步骤 2
    • i = 2i * i = 4,继续下一次循环。
  4. 步骤 3
    • i = 3i * i = 9,此时 9 > 8,返回前一个数 2 作为平方根。

暴力法的优缺点

  • 优点:实现简单,直观。
  • 缺点:对于较大的输入,时间复杂度为 O(x^1/2),效率较低。

1.4.2 二分查找法

二分查找法是一种更高效的方式,通过利用平方根的有序性,在查找过程中不断缩小区间,快速找到平方根。

算法步骤:
  1. 初始化左右指针
    • left 指向 1right 指向 x
  2. 进行二分查找
    • 计算中间位置 mid = left + (right - left + 1) / 2
    • 如果 mid * mid <= x,说明平方根可能在右半部分,更新 left = mid
    • 如果 mid * mid > x,说明平方根在左半部分,更新 right = mid - 1
  3. 结束条件:当 left == right 时,查找结束,此时 left 就是平方根。

图解分析

假设 x = 8,我们通过二分查找来找到平方根:

  1. 初始状态
    • left = 1right = 8
    • 计算 mid = (1 + 8 + 1) / 2 = 5,此时 5 * 5 = 25 > 8,更新 right = 4
  2. 步骤 1
    • left = 1right = 4
    • 计算 mid = (1 + 4 + 1) / 2 = 3,此时 3 * 3 = 9 > 8,更新 right = 2
  3. 步骤 2
    • left = 1right = 2
    • 计算 mid = (1 + 2 + 1) / 2 = 2,此时 2 * 2 = 4 <= 8,更新 left = 2

结束状态:当 left == right == 2,我们找到了平方根 2


C++代码实现
class Solution {
public:int mySqrt(int x) {if (x < 1) return 0; // 处理边界情况int left = 1, right = x;while (left < right) {long long mid = left + (right - left + 1) / 2; // 防止溢出if (mid * mid <= x) {left = mid;  // 继续向右半部分查找} else {right = mid - 1;  // 继续向左半部分查找}}return left;  // 返回平方根}
};

易错点提示
  1. 防止溢出:在计算中间位置 mid 时,使用 long long 类型,以避免 mid * mid 超出 int 的范围导致溢出。
  2. 边界条件:需要正确处理 x = 0x = 1 的情况。

代码解读
  • 时间复杂度:每次查找都会将查找范围缩小一半,因此时间复杂度为 O(log n)
  • 空间复杂度:仅使用了常数级的额外空间,空间复杂度为 O(1)

写在最后

二分查找算法总结

二分查找并不是通过死记模板就能轻松解决所有问题的。其核心在于分析题意,并据此确定搜索区间。理解问题背后的逻辑,明确要搜索的区间,才能灵活编写二分查找的代码。模板只是工具,关键在于理解和应用。

重要的三点:

  • 分析题意,确定搜索区间:根据不同的题目,合理分析查找的区间,避免死记硬套模板。
  • 理解区间变化:明确什么时候该舍弃左边区间,什么时候舍弃右边区间,并根据题目特点动态调整指针。
  • 不要纠结模板形式:不必执着于左闭右开、左闭右闭等模板,最重要的是理解算法背后的区间划分逻辑。

模板记忆技巧

  1. 三段式与两段式的选择
    • 在面对不同题目时,不要强行套用模板。通过分析问题中的搜索区间变化,合理选择三段式(左右都参与)或两段式(左右边界一边不参与)。

两段式的特殊处理:

在二分查找中,如何处理中间值 mid 的计算至关重要,特别是在更新左右指针的情况下,需要正确地选择向上取整或向下取整,否则可能会出现死循环。

  • left = mid:为了避免死循环,应当向上取整。因为此时 left 不变,如果不向上取整,mid 将会一直是 left,无法突破当前的循环状态,导致死循环。

    • 计算公式为:mid = left + (right - left + 1) / 2
  • right = mid:应当向下取整。这样可以保证每次 right 都会减少,逐步缩小搜索区间。

    • 计算公式为:mid = left + (right - left) / 2

以上就是关于【优选算法篇】在分割中追寻秩序:二分查找的智慧轨迹啦的内容啦,各位大佬有什么问题欢迎在评论区指正,您的支持是我创作的最大动力!❤️

在这里插入图片描述

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

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

相关文章

git clone报错fatal: pack has bad object at offset 186137397: inflate returned 1

git clone报错fatal: pack has bad object at offset 186137397: inflate returned 1 逐步拷贝 https://stackoverflow.com/questions/27653116/git-fatal-pack-has-bad-object-at-offset-x-inflate-returned-5 https://www.cnblogs.com/Lenbrother/p/17726195.html https://…

在UE引擎中使用spine动画(1)

注意事项&#xff0c;spine的版本必须和UE插件的版本相同。 1.最重要的是“修改骨架名称。&#xff08;影响在UE引擎中的资产名称&#xff09; 2.导出操作&#xff08;把非必要的数据取消掉&#xff0c;可能会影响UE导入&#xff09;。 3.纹理打包&#xff08;一般默认&#…

程序员:数字时代的先锋

随着科技的不断进步&#xff0c;程序员这一职业群体逐渐成为社会中不可或缺的一部分。他们以智慧和汗水为世界带来更多的便捷与创新。今天&#xff0c;我们将庆祝1024程序员节&#xff0c;这是一个向全球程序员们表达敬意和感激的节日。让我们一同走进程序员的内心世界&#xf…

数字分组求偶数和

问题描述 小M面对一组从 1 到 9 的数字&#xff0c;这些数字被分成多个小组&#xff0c;并从每个小组中选择一个数字组成一个新的数。目标是使得这个新数的各位数字之和为偶数。任务是计算出有多少种不同的分组和选择方法可以达到这一目标。 numbers: 一个由多个整数字符串组…

[ 钓鱼实战系列-基础篇-7 ] 一篇文章教会你搭建邮件钓鱼服务器-1

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

js.杨辉三角和分发饼干

1&#xff0c;链接&#xff1a;118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows …

动态规划-子序列问题——300.最长递增子序列

1.题目解析 题目来源&#xff1a;300.最长递增子序列——力扣 测试用例 2.算法原理 1.状态表示 首先创建一个与数组大小相同的dp表&#xff0c;此时dp[i]表示的是&#xff1a;以第i个位置为结尾的所有子序列中最长递增子序列的长度 2.状态转移方程 此时第i个位置一定是最长递…

国家能源集团携手海康威视研发攻克融合光谱煤质快检技术

10月24日&#xff0c;在国家能源集团准能集团黑岱沟露天煤矿&#xff0c;安装于准能选煤厂785商品煤胶带机中部的煤质快检核心设备&#xff0c;正在对当天装车外运的商品煤煤质进行实时检测。仅两分钟后&#xff0c;涵盖发热量、水分、灰分、硫分等多项指标的数据信息已传输到到…

六.python面向对象

学过C或者Java的同学一定了解过面向对象的相关内容&#xff0c;编程语言一般分为两种设计方式&#xff1a;面向对象、面向过程&#xff0c;早期的编程语言多是面向过程的&#xff0c;由多个过程组合在一起&#xff0c;而Python在设计的时候就是一种面向对象的语言&#xff0c;因…

Room新手入门

Room Room 是所谓的 ORM&#xff08;对象关系映射&#xff09;库 依赖 在项目级 build.gradle 文件中&#xff0c;在 ext 代码块中定义 room_version。 ext {kotlin_version "1.6.20"nav_version "2.4.1"room_version 2.4.2 }在应用级 build.gradle…

【JavaEE初阶】深入理解TCP协议中的封装分用以及UDP和TCP在网络编程的区别

前言 &#x1f31f;&#x1f31f;本期讲解关于TCP/UDP协议的原理理解~~~ &#x1f308;上期博客在这里&#xff1a;【JavaEE初阶】入门视角-网络原理的基础理论的了解-CSDN博客 &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; …

【Spring】关于Spring中aware相关接口的作用

Aware 接口的回调方法是在 Bean 实例化之后调用的。具体来说&#xff0c;这些回调方法是在依赖注入完成后&#xff0c;但在 Bean 完全初始化之前调用的。这是 Spring 容器管理 Bean 生命周期的一部分 完成了属性赋值之后&#xff0c;Spring会执行一些回调&#xff0c;包括&…

java中Set,Map,List集合的比较(不包含增删改查函数方法)

目录 1. 集合的简介2. List3. Set4. Map5. 比较5.1 结构特点5.2 实现类5.3 区别 6. 其他问题6.1 集合与数组的区别6.2 哪些集合类是线程安全的 7. 参考链接 1. 集合的简介 所有的集合类和集合接口都在java.util包下。 在内存中申请一块空间用来存储数据&#xff0c;在Java中集…

C++加载sqlite3数据库文件

db数据库文件简单轻便&#xff0c;形式上可以像excel数据那样&#xff0c;但是解析的时候却有很大的灵活性。使用Python解析db数据已经是很简单的事情&#xff0c;使用专门的数据库可视化工具&#xff0c;通过sql语句查询内容也是有手就行&#xff0c;也许C也不难&#xff0c;但…

31省226地级市极端天气和气候风险指数 (1993-2023年)附下载链接

1993-2023年31省、226个地级市极端天气和气候风险指数 下载链接-点它&#x1f449;&#x1f449;&#xff1a;1993-2023年31省、226个地级市极端天气和气候风险指数-最新出炉.zip 数据名称 1993&#xff5e;2023 省市级气候风险指数 数据来源 nature 子刊&#xff0c;已转…

DEPT:DECOMPOSED PROMPT TUNING FOR PARAMETER-EFFICIENT FINE-TUNING

论文汇总 当前的问题 (1)Prompt Tuning通常收敛缓慢&#xff0c;并且对初始化敏感&#xff1b; (2)Prompt Tuning延长了输入序列的总长度&#xff0c;从而加剧了计算需求(即训练/推理时间和内存成本)&#xff0c;这是由于Transformer的二次复杂度(Vaswani et al, 2017)。 解…

鸿蒙开发:实现全局异常捕获和异常查看

前言 开发中的异常信息&#xff0c;我们很容易排查&#xff0c;直接可以在控制台中就可以查看&#xff0c;但是&#xff0c;提交给测试同学或者上线后的异常信息&#xff0c;我们如何获取呢&#xff1f;这里我们很容易想起&#xff0c;三方sdk&#xff0c;比如常见的腾讯Bugly…

基于Springboot+Vue的学校课程管理系统(含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…

vue之打包配置环境

一直以来都是用脚手架直接搭建的项目,也很少去深究,前两天因为环境配置变更,稍微研究了下 NODE_ENV 首先 在evn.xxx 的配置文件里 一定要有的NODE_ENV NODE_ENV 默认只有两种状态即development和production development: 指代本地开发即localhost环境&#xff08;本地的开发…

VirtualBox虚拟机桥接模式固定ip详解

VirtualBox虚拟机桥接模式固定ip详解 VirtualBox 桥接设置Ubuntu 24.04使用固定IP问题记录 VirtualBox 桥接设置 为什么设置桥接模式&#xff1f;桥接模式可以实现物理机和虚拟机互相通信&#xff0c;虚拟机也可以访问互联网&#xff08;推荐万金油&#xff09;&#xff0c;物…