算法沉淀——二分查找(leetcode真题剖析)

news2024/12/23 23:41:54

在这里插入图片描述

算法沉淀——二分查找

  • 01.二分查找
  • 02.在排序数组中查找元素的第一个和最后一个位置
  • 03.搜索插入位置
  • 04.x 的平方根
  • 05.山脉数组的峰顶索引
  • 06.寻找峰值
  • 07.寻找旋转排序数组中的最小值
  • 08.LCR 173. 点名

二分查找(Binary Search)是一种在有序数组中查找特定元素的算法。该算法的基本思想是通过每一次比较,将查找范围缩小一半,最终找到目标元素或者确定目标元素不存在。

二分查找的步骤

  1. 初始化: 定义两个指针,leftright,分别指向数组的起始和结束位置。
  2. 循环条件:left <= right 的条件下,执行以下步骤。
  3. 计算中间位置: 计算中间位置的索引 mid,可以使用 mid = (left + right) / 2 或者 mid = left + (right - left) / 2。这样可以防止整数溢出。
  4. 比较中间元素: 将目标元素与数组中间位置的元素进行比较。
    • 如果目标元素等于中间元素,查找成功,返回中间元素的索引。
    • 如果目标元素小于中间元素,说明目标元素可能在左半部分,更新 right = mid - 1
    • 如果目标元素大于中间元素,说明目标元素可能在右半部分,更新 left = mid + 1
  5. 重复步骤: 回到步骤 3,直到 left 大于 right,此时查找范围为空,表示目标元素不存在。

二分查找的优势

  • 效率高: 由于每一次比较都将查找范围减半,二分查找的时间复杂度是 O(log n),其中 n 是数组的长度。
  • 适用条件: 二分查找要求数组必须是有序的,但在有序数组中查找元素时,它是一种非常高效的算法。

二分查找的局限性

  • 必须有序(大多数情况下): 二分查找要求数组是有序的,如果数组是无序的,需要先进行排序。
  • 不适用于链表: 二分查找通常用于数组,对于链表结构,由于无法直接通过下标访问元素,不太适用。
  • 只能查找特定值: 二分查找主要用于查找特定值,对于查找范围不明确的情况,可能不太合适。

二分查找的应用场景

  • 在有序数组中查找特定元素。
  • 寻找有序数组中的上下界。
  • 在数值范围内寻找满足条件的值。

二分查找基本模板

朴素版(适用于最基础的二分)

while(left<=right){
	int mid=left+(right-left)/2;
	if(条件)
		left=mid+1;
	else if(条件)
		right=mid-1;
	else
		return ...;
}

全能版(均可适用)

①查找左边界

while(left<right){
	int mid=left+(right-left)/2;
	if(条件)
		left=mid+1;
	else
		right=mid;
}

②查找右边界

while(left<right){
	int mid=left+(right-left+1)/2;
	if(条件)
		left=mid;
	else
		right=mid-1;
}

全能版的写法需要根据不同的情况做出相应改变,比如这里的中间值为什么要+1再除,是因为最下面的条件mid-1,如果没有-1,那么上面也不需要+1,这样做是为了防止进入死循环,这个模板仅供参考,切勿死记硬背,实践出真知,适合自己的才最重要。

01.二分查找

题目链接:https://leetcode.cn/problems/binary-search/

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 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

思路

这里就是最基础的朴素二分,我们直接写上去就可以了,不熟悉二分最好自己动手写一遍,对后面的二分题就会有更深入的了解,打牢基础。

  1. 初始化两个指针 leftright 分别指向数组的起始位置和结束位置。
  2. while 循环中,通过计算中间位置 mid(避免整数溢出的写法),对比中间元素与目标元素的大小关系,从而缩小查找范围。
    • 如果 nums[mid] > target,说明目标元素可能在左半部分,更新 right = mid - 1
    • 如果 nums[mid] < target,说明目标元素可能在右半部分,更新 left = mid + 1
    • 如果 nums[mid] == target,找到目标元素,返回 mid
  3. 循环直到 left 大于 right,此时查找范围为空,返回 -1 表示目标元素不存在。

代码

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) right=mid-1;
            else if(nums[mid]<target) left=mid+1;
            else return mid;
        }
        return -1;
    }
};

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

题目链接:https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/

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

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

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

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:

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

思路

这里题目指定时间复杂度为 O(log n) 的算法,说明就是要让我们使用二分的算法,这里需要注意两个问题,第一个是边界问题,避免死循环,第二就是这里找两个值,我们可以分成两个二分来找,这样我们可以将逻辑捋清楚,这里模板中左边界与有边界两个版本都能用上。

  1. 首先,判断数组是否为空,如果为空,则直接返回 {-1, -1},表示目标元素不存在于数组中。
  2. 利用二分查找找到目标元素的起始位置,首先在数组中找到第一个大于等于 target 的元素的位置。这个过程通过维护两个指针 leftright,在循环中不断缩小查找范围,最终 left 的位置就是目标元素的起始位置。
  3. 如果找到的 nums[left] 不等于 target,说明目标元素不存在,返回 {-1, -1}。
  4. 如果找到了目标元素的起始位置 begin,则重置 leftright,利用二分查找找到目标元素的结束位置。在这一步中,找到第一个大于 target 的位置的前一个位置,即 right
  5. 返回结果,即目标元素的起始位置和结束位置。

代码

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if(!nums.size()) return {-1,-1};

        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[left]!=target) return {-1,-1};
        int begin=left;
        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 {begin,right};
    }
};

03.搜索插入位置

题目链接:https://leetcode.cn/problems/search-insert-position/

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

请必须使用时间复杂度为 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

思路

和上一题一样,题目指定时间复杂度为 O(log n) 的算法,说明就是要让我们使用二分的算法,这里我们直接使用左边界二分即可,注意边界问题,比如target值大于最后一个值,需要考虑。

  1. 初始化两个指针 leftright 分别指向数组的起始位置和结束位置。
  2. while 循环中,通过计算中间位置 mid(避免整数溢出的写法),对比中间元素与目标元素的大小关系,从而缩小查找范围。
    • 如果 nums[mid] < target,说明目标元素可能在右半部分,更新 left = mid + 1
    • 如果 nums[mid] >= target,说明目标元素可能在左半部分,更新 right = mid
  3. 循环直到 left >= right,此时 left 就是插入位置,因为 left 所指的元素是第一个大于或等于 target 的元素。
  4. 最后判断 nums[left]target 的关系:
    • 如果 nums[left] < target,则插入位置在 left + 1
    • 否则,插入位置在 left
  5. 返回插入位置。

代码

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;
        }
        if(nums[left]<target) return left+1;
        return left;
    }
};

04.x 的平方根

题目链接:https://leetcode.cn/problems/sqrtx/

给你一个非负整数 x ,计算并返回 x算术平方根

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

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

示例 1:

输入:x = 4
输出:2

示例 2:

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

思路

这里我们使用二分是在暴力循环的基础上改进而来的,需要注意的是边界问题和溢出问题

  1. 首先,判断 x 的值,如果小于 1,则直接返回 0,因为在非负整数范围内不存在小于 1 的平方根。
  2. 初始化两个指针 leftright,分别指向 1 和 x
  3. while 循环中,通过计算中间位置 mid(使用 (right - left + 1) / 2 避免整数溢出),对比中间元素的平方与 x 的大小关系,从而缩小查找范围。
    • 如果 mid * mid <= x,说明目标平方根可能在右半部分,更新 left = mid
    • 如果 mid * mid > x,说明目标平方根可能在左半部分,更新 right = mid - 1
  4. 循环直到 left >= right,此时 leftright 就是平方根的整数部分。
  5. 返回 right

代码

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 right;
    }
};

05.山脉数组的峰顶索引

题目链接:https://leetcode.cn/problems/peak-index-in-a-mountain-array/

符合下列属性的数组 arr 称为 山脉数组

  • arr.length >= 3
  • 存在i(0 < i < arr.length - 1)使得:
    • arr[0] < arr[1] < ... arr[i-1] < arr[i]
    • arr[i] > arr[i+1] > ... > arr[arr.length - 1]

给你由整数组成的山脉数组 arr ,返回满足 arr[0] < arr[1] < ... arr[i - 1] < arr[i] > arr[i + 1] > ... > arr[arr.length - 1] 的下标 i

你必须设计并实现时间复杂度为 O(log(n)) 的解决方案。

示例 1:

输入:arr = [0,1,0]
输出:1

示例 2:

输入:arr = [0,2,1,0]
输出:1

示例 3:

输入:arr = [0,10,5,2]
输出:1

思路

看到这题很多并不会想到使用二分去做,因为概念里写的使用二分一定要有序,但是这里是可以使用二分的思想来做这道题的,所以我们要将思路打开,根据题意这里山顶不会是左右的边界值,所以这里我们只要使用二分找出数组的最大值就行了

  1. 初始化两个指针 leftright,分别指向二分的起始位置和结束位置(边界不需要考虑)。
  2. while 循环中,通过计算中间位置 mid(使用 (right - left) / 2 避免整数溢出),对比中间元素与其右侧元素的大小关系,从而缩小查找范围。
    • 如果 arr[mid] < arr[mid + 1],说明峰值可能在右半部分,更新 left = mid + 1
    • 如果 arr[mid] >= arr[mid + 1],说明峰值可能在左半部分,更新 right = mid
  3. 循环直到 left >= right,此时 leftright 就是山脉数组的峰值。
  4. 返回 right

这个算法的核心思想是通过二分查找,在山脉数组中找到峰值的索引。在山脉数组中,峰值是指一个位置左侧的元素严格单调递增,右侧的元素严格单调递减的位置。因此,通过比较中间元素与其右侧元素的大小关系,可以缩小查找范围,最终找到峰值的位置。

代码

class Solution {
public:
    int peakIndexInMountainArray(vector<int>& arr) {
        int left=1,right=arr.size()-2;
        while(left<right){
            int mid = left+(right-left)/2;
            if(arr[mid]<arr[mid+1]) left=mid+1;
            else right=mid;
        }
        return right;
    }
};

06.寻找峰值

题目链接:https://leetcode.cn/problems/find-peak-element/

峰值元素是指其值严格大于左右相邻值的元素。

给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞

你必须实现时间复杂度为 O(log n) 的算法来解决此问题。

示例 1:

输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。

示例 2:

输入:nums = [1,2,1,3,5,6,4]
输出:1 或 5 
解释:你的函数可以返回索引 1,其峰值元素为 2;
     或者返回索引 5, 其峰值元素为 6。

思路

基本和上一题的二分思想是一致的,但是这里需要考虑边界问题,因此不能直接去除首尾。

  1. 初始化两个指针 leftright,分别指向数组的起始位置和结束位置。
  2. while 循环中,通过计算中间位置 mid(使用 (right - left) / 2 避免整数溢出),对比中间元素与其右侧元素的大小关系,从而缩小查找范围。
    • 如果 nums[mid] < nums[mid + 1],说明峰值可能在右半部分,更新 left = mid + 1
    • 如果 nums[mid] >= nums[mid + 1],说明峰值可能在左半部分,更新 right = mid
  3. 循环直到 left >= right,此时 leftright 就是无序数组的峰值。
  4. 返回 left

代码

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        int left=0,right=nums.size()-1;
        while(left<right){
            int mid = left+(right-left)/2;
            if(nums[mid]<nums[mid+1]) left=mid+1;
            else right=mid;
        }
        return left;
    }
};

07.寻找旋转排序数组中的最小值

题目链接:https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array/

已知一个长度为 n 的数组,预先按照升序排列,经由 1n旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
  • 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]

注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]]

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。

示例 2:

输入:nums = [4,5,6,7,0,1,2]
输出:0
解释:原数组为 [0,1,2,4,5,6,7] ,旋转 3 次得到输入数组。

示例 3:

输入:nums = [11,13,15,17]
输出:11
解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。

思路

这里我们使用二分法使用中间值与最右边的值相比较,若中间值大,说明最小值一定在右边,反之在左边,这里使用二分法不用考虑数组旋转了几次。

  1. 初始化两个指针 leftright,分别指向数组的起始位置和结束位置。
  2. 记录数组最右侧元素的值为 x,作为旋转的轴。这个轴元素是数组的最小元素。
  3. while 循环中,通过计算中间位置 mid(使用 (right - left) / 2 避免整数溢出),对比中间元素与 x 的大小关系,从而缩小查找范围。
    • 如果 nums[mid] > x,说明最小元素可能在右半部分,更新 left = mid + 1
    • 如果 nums[mid] <= x,说明最小元素可能在左半部分或就是 mid 位置,更新 right = mid
  4. 循环直到 left >= right,此时 leftright 就是数组中的最小元素所在的位置。
  5. 返回 nums[left]

代码

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left=0,right=nums.size()-1;
        int x=nums[right];
        while(left<right){
            int mid=left+(right-left)/2;
            if(nums[mid]>x) left=mid+1;
            else right=mid;
        }
        return nums[left];
    }
};

08.LCR 173. 点名

题目链接:https://leetcode.cn/problems/que-shi-de-shu-zi-lcof/

某班级 n 位同学的学号为 0 ~ n-1。点名结果记录于升序数组 records。假定仅有一位同学缺席,请返回他的学号。

示例 1:

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

示例 2:

输入: records = [0, 1, 2, 3, 4, 5, 6, 8]
输出: 7

思路

这道题其实有多种解法,我们使用二分解决可以效率非常高,这里只需要注意边界问题,即最大学号缺席。

  1. 初始化两个指针 leftright,分别指向数组的起始位置和结束位置。
  2. while 循环中,通过计算中间位置 mid(使用 (right - left) / 2 避免整数溢出),对比中间元素 records[mid]mid 的大小关系,从而缩小查找范围。
    • 如果 records[mid] == mid,说明漏考勤的学生可能在右半部分,更新 left = mid + 1
    • 如果 records[mid] != mid,说明漏考勤的学生可能在左半部分或就是 mid 位置,更新 right = mid
  3. 循环直到 left >= right,此时 leftright 就是漏考勤的学生的位置。
  4. 返回 right == records[right] ? right + 1 : right

代码

class Solution {
public:
    int takeAttendance(vector<int>& records) {
        int left=0,right=records.size()-1;
        while(left<right){
            int mid = left + (right-left)/2;
            if(records[mid]==mid) left=mid+1;
            else right=mid;
        }

        return right==records[right]?right+1:right;
    }
};

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

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

相关文章

【服务器APP】利用HBuilder X把网页打包成APP

目录 &#x1f33a;1. 概述 &#x1f33c;1.1 新建项目 &#x1f33c;1.2 基础配置 &#x1f33c;1.3 图标配置 &#x1f33c;1.4 启动界面配置 &#x1f33c;1.5 模块配置 &#x1f33c;1.6 打包成APP &#x1f33a;1. 概述 探讨如何将网页转化为APP&#xff0c;这似乎…

【大厂AI课学习笔记】1.3 人工智能产业发展(1)

我国人工智能政策&#xff0c;分为5个阶段。从探索期&#xff0c;到后面的4个阶段。 MORE:&#xff08;以下为文心一言4.0的参考内容&#xff0c;和腾讯课程资料的分阶段&#xff0c;略有不同&#xff09; 我国的人工智能政策发展可以大致分为以下几个阶段&#xff0c;每个阶段…

网络防御安全知识(第三版)

配置黑洞路由 --- 黑洞路由即空接口路由&#xff0c;在NAT地址池中的地址&#xff0c;建议配置达到这个地址指 向空接口的路由&#xff0c;不然&#xff0c;在特定环境下会出现环路。&#xff08;主要针对地址池中的地址和出接口地址 不再同一个网段中的场景。&#xff09; …

一文解锁——那些你不太了解的AI!

ChatGPT现象级走红&#xff0c;国内也有文心一言等模型紧随其后&#xff0c;彻底将大语言模型送上大热门。 不管是你是否深度应用过这些模型&#xff0c;不可否认的是&#xff0c;AI已经彻底地融入我们的生活&#xff0c;甚至成为赚钱利器。除了ChatGPT和百度的文心一言&#…

力扣712. 两个字符串的最小ASCII删除和

动态规划 思路&#xff1a; 假设 dp[i][j] 是 s1 长度 i 和 s2 长度 j 两个字符串的最小 ASCII 删除和&#xff1b;dp[i][j] 可以由&#xff1a; 如果 s1 的第 i 个字符&#xff08;s1[i - 1]&#xff09;和 s2 的第 j 个字符&#xff08;s2[j - 1]&#xff09;不相等&#xf…

详解SpringCloud微服务技术栈:ElasticSearch实战(旅游类项目)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;详解SpringCloud微服务技术栈&#xff1a;ElasticSearch实践2——RestClient查询并处理文档 &#x1f4da;订阅专栏&#xff1a;…

【JavaScript 基础入门】01 编程语言和计算机基础

编程语言和计算机基础 目录 编程语言和计算机基础1 - 编程语言1.1 编程1.2 计算机语言1.3 编程语言1.4 翻译器1.5 编程语言和标记语言区别1.6 总结 2 - 计算机基础2.1 计算机组成2.2 数据存储2.3 数据存储单位2.4 程序运行 1 - 编程语言 1.1 编程 编程&#xff1a; 就是让计算…

运放反馈电阻上并联小电容的作用

这是一个同相比例运算放大电路&#xff0c; Rf是反馈电阻 有的电路还会在反馈电阻上并联一个小电容&#xff0c;一般在几pF到几十pF。 那么这个电容有什么作用呢&#xff1f;其实这个电容是一个相位补偿电容&#xff0c;防止运放自激振荡的。另外这个电容也有抑制高频噪声的作用…

GoogleNet Inception v2 和 Inception v3详解

1 GoogleNet Inception v2 v1具体结构&#xff1a; v2具体结构&#xff1a; 1 引入Batch Normalization&#xff08;BN&#xff09;: Inception v2在每个卷积层之后引入了BN。这有助于解决深层网络中的梯度消失问题&#xff0c;同时加快训练过程并提高模型的收敛速度。BN通过…

鸿蒙首批原生应用!无感验证已完美适配鸿蒙系统

顶象无感验证已成功适配鸿蒙系统&#xff0c;成为首批鸿蒙原生应用&#xff0c;助力鸿蒙生态的快速发展。 作为全场景分布式操作系统&#xff0c;鸿蒙系统旨在打破不同设备之间的界限&#xff0c;实现极速发现、极速连接、硬件互助、资源共享。迄今生态设备数已突破8亿台&…

[论文阅读] |RAG评估_Retrieval-Augmented Generation Benchmark

写在前面 检索增强能够有效缓解大模型存在幻觉和知识时效性不足的问题&#xff0c;RAG通常包括文本切分、向量化入库、检索召回和答案生成等基本步骤。近期组里正在探索如何对RAG完整链路进行评估&#xff0c;辅助阶段性优化工作。上周先对评估综述进行了初步的扫描&#xff0…

PAT-Apat甲级题1003(python和c++实现)下

PTA | 1003 Emergency 书接上回&#xff0c;上次我们使用了python实现无向带权图与DFS算法的设计&#xff0c;本次我们将使用C对本题进行解答&#xff0c;思路和题目分析同上一节内容&#xff0c;本次我们将在上一节的基础上继续实现。 okok现在又是激动人心的手搓代码时间&a…

JMeter性能测试实战

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

喝酒筛子小游戏集合源码微信小程序喝酒骰子程序带流量主版本源码酒桌玩筛子源码

2023新版酒桌小游戏喝酒小程序源码-&#xff08;流量主版本&#xff09; 修改增加了广告位 根据文档直接替换&#xff0c;原版本没有广告位 直接上传源码到开发者端即可 通过后改广告代码&#xff0c;然后关闭广告展示提交&#xff0c;通过后打开即可 无广告引流 流量主版…

Spring MVC 基本知识

知识回顾 Tomcat 是 Servlet 容器&#xff0c;会解析 Java Web 应用下的 WEB-INF/web.xml 文件&#xff0c;得到相关的 Servlet 组件。 原理解析 Spring MVC 实际是定义了一个 DispatcherSevlet 来统一管理当前 Web 应用下的 Path 路径。在 DispatchSevlet 中持有了一个 Spr…

存储技术架构演进

一. 演进过程 存储技术架构的演进主要是从集中式到分布式的一种呈现&#xff0c;集中式存储模式凭借其在稳定性和可靠性方面的优势成为许多业务数据库的数据存储首选&#xff0c;顾名思义&#xff0c;集中式存储主要体现在集中性&#xff0c;一套集中式管理的存储系统&#xff…

鸿蒙开发-UI-布局-网格

鸿蒙开发-UI-布局 鸿蒙开发-UI-布局-线性布局 鸿蒙开发-UI-布局-层叠布局 鸿蒙开发-UI-布局-弹性布局 鸿蒙开发-UI-布局-相对布局 鸿蒙开发-UI-布局-格栅布局 鸿蒙开发-UI-布局-列表 文章目录 前言 一、基本概念 二、开发布局 1.排列方式 2.设置行列间距 三、应用特性 1.网格数…

数字图像处理(实践篇)三十五 OpenCV-Python在图像上进行SQRBox滤波操作实践

目录 一 方框滤波 二 涉及的函数 三 实践 一 方框滤波 方框滤波是均值滤波的一般形式。二者的不同之处在于在均值滤波中,将滤波器中所有的像素值求和后的平均值作为滤波后结果,方框滤波也是求滤波器内所有像素值的之和࿰

AGP更改gradle版本无效的解决方案

从Github下载了一个项目&#xff0c;非常激进&#xff0c;AGP版本8.4.0&#xff0c;而我的AS只支持到8.2.0 详见&#xff1a;https://developer.android.com/build/releases/gradle-plugin?buildsystemndk-build&hlzh-cn#android_gradle_plugin_and_android_studio_compa…

国标GB/T 28181详解:GB/T28181基本注册流程和注销流程

目 录 一、基本要求 二、注册流程 三、注销流程 四、产品说明 五、参考 一、基本要求 根据《GB/T 28181-2022》第9章关于注册和注销的描述&#xff0c;GB28181的注册和注销应满足下面这些要求&#xff1a; SIP 客户端网关、SIP 设备、联网系统等 SIP 代理…