当前位置: 首页 > news >正文

AI大模型从0到1记录学习 数据结构和算法 day20

4.3 分治算法
4.3.1 概述
分治算法的基本思想为:将原问题递归的分解为若干个(通常是两个以上)规模较小、相互独立且性质相同的子问题,直到子问题足够简单,简单到可以直接求解。然后再返回结果,逐个解决上层问题。
实际上,前文提到的归并排序算法和快速排序算法都是分治思想的典型应用。
能使用分治算法解决的问题通常需要具备以下特点:
 可分解:问题可以被划分为多个规模较小的子问题。这些子问题通常具有相同的性质,并且可以独立地解决。
 存在基本情况:问题分解的小到一定程度后,就变得非常简单,简单到可以直接求解。
 可合并:可以通过合并多个子问题的解,得到原问题的解。
4.3.2 案例一:汉诺塔
力扣面试题08.06https://leetcode.cn/problems/hanota-lcci/description/
现有三根柱子A、B 和 C 。起始状态下,柱子A上套着圆盘,它们从上到下按照从小到大的顺序排列。要将所有圆盘移到柱子C上,并保持它们的原有顺序不变。在移动圆盘的过程中,需要遵守以下规则:
 圆盘只能从一根柱子顶部拿出,从另一根柱子顶部放入。
 每次只能移动一个圆盘。
 小圆盘必须时刻位于大圆盘之上。

1)思路分析
将规模为n的汉诺塔问题记作f(n)。例如f(3)代表将3个圆盘从A移动至C。
(1)只有1个圆盘

f(1),将圆盘从A移动至C。

(2)有2个圆盘

f(2),借助B将两圆盘从A移动至C,分为3步:
使用f(1)的方法将一个圆盘从A移动至B。
使用f(1)的方法将一个圆盘从A移动至C。
使用f(1)的方法将一个圆盘从B移动至C。
(3)有3个圆盘。

分为3步:
使用f(2)的方法借助C将2个圆盘从A移动至B。
使用f(1)的方法将1个圆盘从A移动至C。
使用f(2)的方法借助A将2个圆盘从B移动至C。
(4)有n个圆盘
分为3步:
使用f(n-1)的方法借助C将n-1个圆盘从A移动至B。
使用f(1)的方法将1个圆盘从A移动至C。
使用f(n-1)的方法借助A将n-1个圆盘从B移动至C。
def print_abc():
“”“打印3个柱子”“”
print(“a:”, a)
print(“b:”, b)
print(“c:”, c)
print()

def hanota(n, source, target, buffer):
# 只有一个盘子时,直接从源柱子移动到目标柱子
if n == 1:
target.append(source.pop())
return

# 1. 将 n-1 个盘子从源柱子移动到缓冲柱子
hanota(n - 1, source, buffer, target)
print_abc()# 2. 将第 n 个盘子从源柱子移动到目标柱子
hanota(1, source, target, buffer)
print_abc()# 3. 将 n-1 个盘子从缓冲柱子移动到目标柱子
hanota(n - 1, buffer, target, source)
print_abc()

if name == “main”:
n = 3
a = list(range(n, 0, -1))
b = []
c = []
hanota(n, a, c, b)
4.3.3 案例二:Karatsuba大整数乘法算法
Karatsuba(卡拉楚巴)算法是一种高效的大整数乘法算法,关键思想是通过分治法减少了传统乘法的计算量,从而降低了乘法的时间复杂度。
现有两个大整数A和B,它们的乘积C=A×B。在传统的朴素乘法算法中,两个n位数的乘积需要进行O(n2)次基本操作。因为每一位数字都需要与另一个数字的每一位相乘,然后再加上进位。
我们将A、B的高位部分和低位部分拆开,取数字长度的一半为m,分别表示为:
A=10m×A1+A0
B=10m×B1+B0
此时可以得到:C=A×B=(10m×A1+A0)×(10m×B1+B0)
=102m×A1×B1 + 10m×(A1×B0+A0×B1) + A0×B0
这个表达式由三项组成:
A1×B1:高位部分的乘积。
A0×B0:低位部分的乘积。
A1×B0+A0×B1:混合部分,涉及到高位与低位的交叉乘积。
注意到,A1×B0+A0×B1可以转换为(A1+A0)×(B1+B0)- A0×B0-A1×B1,即(A1+A0)×(B1+B0)-低位部分的乘积-高位部分的乘积,低位部分乘积和高位部分乘积可以复用,我们只需计算(A1+A0)×(B1+B0),相较于计算A1×B0+A0×B1,减少了1次乘法计算。
令z0=A0×B0
令z1=(A1+A0)×(B1+B0)
令z2= A1×B1
此时结果C=102m× z2 + 10m×(z1−z2−z0) + z0
这样,Karatsuba通过减少了1个乘法操作,将原本的4次乘法运算变成了3次乘法运算,时间复杂度:T(n)=3T(n2)+O(n),O(nlog3)≈O(n1.585)。

def karatsuba(x, y):
“”“卡拉楚巴算法”“”
# 将 x 和 y 转换为字符串
x_str, y_str = str(x), str(y)
n = max(len(x_str), len(y_str))

# 如果存在负数,将其转换为正数再调用 karatsuba
if x_str[0] == "-":return -karatsuba(-x, y)
if y_str[0] == "-":return -karatsuba(x, -y)# 如果只剩1位则返回乘积
if n == 1:return x * y# 确保数字长度一致
x_str = x_str.zfill(n)
y_str = y_str.zfill(n)# 计算分割点
m = n // 2# 将数字划分为高位部分和低位部分
high1, low1 = int(x_str[:-m]), int(x_str[-m:])
high2, low2 = int(y_str[:-m]), int(y_str[-m:])# 递归调用 karatsuba
z0 = karatsuba(low1, low2)
z1 = karatsuba(low1 + high1, low2 + high2)
z2 = karatsuba(high1, high2)return pow(10, 2 * m) * z2 + pow(10, m) * (z1 - z2 - z0) + z0

4.4 动态规划算法
4.4.1 概述
动态规划算法与分治法类似,也是通过将原问题拆分为若干子问题,然后递归求解子问题,最后再组合子问题的解进而得到原问题的解。不同的是,分治算法解决的问题,子问题通常相互独立。而动态规划解决的问题,子问题具有重叠现象,所谓的重叠现象,是指不同的子问题会有相同的子子问题。
对于这些重复的子问题,若不加干预,会进行多次的重复计算,效率低下。动态规划意义就是,能够保证每个重复的子问题只计算一次,其解决问题的思路就是将计算过的子问题保存起来,后续计算相同子问题时,便可直接获取结果。
动态规划算法的实现方式分为自上而下的记忆化递归和自下而上的迭代。自上而下的递归方式只需考虑原问题到子问题的递归公式,而无序考虑子问题的执行顺序;而自下而上的迭代方式,除了需要考虑递推关系,还需要确保子问题从小到大依次执行。
4.4.2 案例一:爬楼梯
力扣70题https://leetcode.cn/problems/climbing-stairs/description/
爬有n个台阶的楼梯,每次可以爬1或2个台阶。有多少种不同的方法可以爬到楼顶?
1)方法一
由于每次只能个或个台阶,所以第n个台阶可能是从第n-1个台阶爬1阶上来的,也可能是从第n-2个台阶爬2阶上来的,所以爬到第n阶的方法数就等于爬到第n-1阶的方法数加上爬到第n-2阶的方法数。故可以得到状态转移方程:f(n) = f(n-1) + f(n-2)。
def climb(n):
if n == 1:
return 1
elif n == 2:
return 2
else:
return climb(n - 1) + climb(n - 2)
2)方法二
既然f(n) = f(n-1) + f(n-2),那么我们也可以自下而上从1阶台阶开始逐渐增加,并记录当前阶方法数和当前阶-1的方法数。
def climb(n):
pre = 1
cur = 1
for _ in range(1, n):
pre, cur = cur, pre + cur
return cur
4.4.3 案例二:最大的连续子数组之和
力扣53题https://leetcode.cn/problems/maximum-subarray/description/
找出整数数组nums中数组之和最大的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
 输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
 输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
1)思路分析
用f(x)表示以x结尾的最大子数组之和,考虑处于位置i时,有两种选择:
 与之前的子数组组成连续子数组,此时子数组之和f(i) = f(i-1) + nums[i]。
 中断连续,从头开始一个新的连续子数组,此时f(i) = nums[i]。
得到状态转移方程:f(i) = max( f(i-1) + nums[i] , nums[i] )。
持续组成连续子数组,除非连续子数组之和已经<0,此时中断连续。
def max_subarray(nums):
result, f = nums[0], 0
for i in nums:
# 连续子数组之和若小于0,则中断连续
if f < 0:
f = 0
# 累加连续子数组之和
f += i
# 更新最大值
if result < f:
result = f
return result
4.4.4 案例三:0-1背包
0-1背包问题是一个经典的动态规划问题。其基本描述是:给定一组物品,每个物品都有一个重量和一个价值,在背包容量有限的情况下,如何选择物品放入背包,使得背包中物品的总价值最大化,且总重量不超过背包的容量。
 物品:有n个物品,每个物品i的重量为weight[i]和价值value[i]。
 背包容量:背包可以承载的最大重量为W。
 目标:选择若干物品放入背包,使得总重量不超过W,且总价值最大。

1)方法一
(1)定义状态
定义一个二维数组 dp[i][j],表示前i个物品中,总重量不超过j的情况下,能够取得的最大价值。
 i:表示考虑第i个物品。
 j:表示背包当前容量为j。
(2)状态转移
对于每个物品i,有两个选择:
 不选第i个物品:此时最大价值就是前i−1个物品在容量j下的最大价值,即 dp[i−1][j]。
 选第i个物品:此时背包剩余容量为j−weighti,所以最大价值为valuei+dp[i−1][j−weighti],前提是 j≥wi。
状态转移方程:dp[i][j] =max( dp[i−1][j] , valuei+dp[i−1][j−weighti] )
最大价值会存储在 dp[n][W]中,其中n是物品的数量,W是背包的最大容量。
(3)实现步骤
 初始化二维数组dp,i行、W+1列,因为要存放背包容量为0~W时的状态。
 循环中每次增加一个可选物品。
 每增加一个可选物品后遍历背包容量为0~W。考虑该物品是否放得下背包,如果放得下,将放进去后和不放进去进行比较。

def knapsack(weights, values, W):
n = len(weights)
# 初始化二维数组dp,dp[i][j]表示前i个物品中,背包容量为j时的最大价值
dp = [[0] * (W + 1) for _ in range(n)]

# 每次增加一个可选物品,增加物品后遍历一次背包重量
for i in range(n):for j in range(1, W + 1):# 如果当前物品放的进背包,进行比较if weights[i] <= j:dp[i][j] = max(dp[i - 1][j], values[i] + dp[i - 1][j - weights[i]])# 如果当前物品放不进背包,使用上轮相同j的状态else:dp[i][j] = dp[i - 1][j]print(f"前{i + 1}个物品,背包容量为{j}时")for row in range(len(dp)):print(dp[row])return dp[n - 1][W]

if name == “main”:
weights = [1, 2, 3] # 物品的重量
values = [3, 2, 6] # 物品的价值
W = 3 # 背包的最大容量
print(knapsack(weights, values, W))
2)方法二
可以看到在方法一中,我们每轮遍历时只用到上1轮的结果,与这一轮的结果无关,因此我们只用一维数组存储上1轮的结果即可。
并且遍历时需要从后往前遍历,防止这轮结果将还需要用到的上轮结果覆盖。
并且不用全部遍历,遍历到背包当前重量刚好大于当前物品重量即可。
def knapsack(weights, values, W):
n = len(weights)
dp = [0] * (W + 1)
for i in range(n):
for j in range(W, weights[i] - 1, -1): # 从后往前遍历
dp[j] = max(dp[j], values[i] + dp[j - weights[i]])
return dp[W]

if name == “main”:
weights = [1, 2, 3] # 物品的重量
values = [3, 2, 6] # 物品的价值
W = 3 # 背包的最大容量
print(knapsack(weights, values, W))
4.4.5 案例四:完全背包
完全背包问题是0-1背包问题的一种扩展。与0-1背包不同,完全背包问题允许每个物品可以被选取多次,也就是说,物品的数量没有限制。
1)方法一
(1)定义状态
定义一个二维数组 dp[i][j],表示前i个物品中,总重量不超过j的情况下,能够取得的最大价值。
 i:表示考虑第i个物品。
 j:表示背包当前容量为j。
(2)状态转移
相较于0-1背包,仅有选择放入第i个物品时发生了变化。
对于每个物品i,有两个选择:
 不选第i个物品:与0-1背包相同,此时最大价值就是前i−1个物品在容量j下的最大价值,即 dp[i−1][j]。
 选第i个物品:此时背包剩余容量为j−weighti,所以最大价值为valuei+dp[i][j−weighti]。
状态转移方程:dp[i][j] =max( dp[i−1][j] , valuei+dp[i][j−weighti] )
状态转移方程相较于0-1背包问题仅有一处 i-1 变为了 i。
(3)实现步骤
 初始化二维数组dp,i行、W+1列,因为要存放背包容量为0~W时的状态。
 循环中每次增加一个可选物品。
 每增加一个可选物品后遍历背包容量为0~W。考虑该物品是否放得下背包,如果放得下,将放进去后和不放进去进行比较。

def knapsack(weights, values, W):
n = len(weights)
# 初始化二维数组dp,dp[i][j]表示前i个物品中,背包容量为j时的最大价值
dp = [[0] * (W + 1) for _ in range(n)]

# 每次增加一个可选物品,增加物品后遍历一次背包重量
for i in range(n):for j in range(1, W + 1):# 如果当前物品放的进背包,进行比较if weights[i] <= j:dp[i][j] = max(dp[i - 1][j], values[i] + dp[i][j - weights[i]])# 如果当前物品放不进背包,使用上轮相同j的状态else:dp[i][j] = dp[i - 1][j]print(f"前{i + 1}个物品,背包容量为{j}时")for row in range(len(dp)):print(dp[row])return dp[n - 1][W]

if name == “main”:
weights = [1, 2, 3] # 物品的重量
values = [3, 7, 11] # 物品的价值
W = 3 # 背包的最大容量
print(knapsack(weights, values, W))
2)方法二
方法一同样可以优化为一维数组。可以看到在方法一中我们既使用了上1轮结果,也使用了本轮i之前的结果,但是两者上下没有重叠。
这时我们遍历时需要从前向后遍历,因为可能会用到本轮i之前的结果。

def knapsack(weights, values, W):
n = len(weights)
dp = [0] * (W + 1)

for i in range(n):for j in range(weights[i], W + 1):dp[j] = max(dp[j], dp[j - weights[i]] + values[i])return dp[W]

if name == “main”:
weights = [1, 2, 3] # 物品的重量
values = [3, 7, 11] # 物品的价值
W = 3 # 背包的最大容量
print(knapsack(weights, values, W))
4.5 回溯算法
4.5.1 概述
回溯算法是一种通过探索所有可能的解来解决问题的算法。回溯法采用试错的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现,现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。回溯法通常用递归方法来实现。
回溯算法的基本步骤可以总结为:
 选择:在每个决策点选择一个候选解。
 探索:递归地继续在下一个决策点上做选择。
 验证:在每次选择之后,检查当前路径是否满足条件。
 回溯:当某条路径不满足条件或无法继续时,回到上一步,尝试其他可能的选择。
4.5.2 案例一:全排列
力扣46题https://leetcode.cn/problems/permutations/description/
现有一个不含重复数字的数组nums ,返回其所有可能的全排列。
示例:
 输入:nums = [1,2,3]
 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
1)思路分析
实现步骤:
 选择:从待排列的元素中选择一个元素作为当前位置的元素。
 递归:将该元素固定在当前位置后,递归排列下一个元素。
 终止条件:所有位置的元素都已确定,添加到结果中并终止递归。
 回溯:回到上一步,撤销当前的选择,尝试下一个可能的元素。

def permute(nums):
result = []

def backtrack(start):# 到达末尾,将此时排列结果添加到最终结果中if start == len(nums):result.append(nums[:])returnfor i in range(start, len(nums)):# 选取当前位置的元素:将要选取的元素与此位置的元素互换if start != i:nums[start], nums[i] = nums[i], nums[start]# 递归处理下一个位置的元素backtrack(start + 1)# 回溯,恢复原始数组if start != i:nums[start], nums[i] = nums[i], nums[start]backtrack(0)
return result

4.5.3 案例二:N皇后
力扣51题https://leetcode.cn/problems/n-queens/description/
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n皇后问题研究的是如何将n个皇后放置在n×n的棋盘上,并且使皇后彼此之间不能相互攻击。给一个整数n,返回所有的解决方案。每一个方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

 输入:n = 4
 输出:[[“.Q…”,“…Q”,“Q…”,“…Q.”],[“…Q.”,“Q…”,“…Q”,“.Q…”]]
解释:如上图所示,4皇后问题存在两个不同的解法。
1)思路分析
实现步骤:
 选择:从棋盘每行中选择一个列放置棋子。
 验证合法性:每次放置一个皇后时,检查该位置是否与其他已经放置的皇后在列或对角线上发生冲突。
 递归:棋子放置位置合法则递归放置下一个棋子。
 终止条件:若所有棋子都放置完则终止递归。
 回溯:回到上一步,尝试下一个位置。
def n_queens(n):
result = []
cols = set() # 记录哪些列有皇后
diag1 = set() # 记录哪些主对角线上有皇后
diag2 = set() # 记录哪些副对角线上有皇后

# 初始化棋盘
board = [["." for _ in range(n)] for _ in range(n)]def backtrack(row):# 如果已经放置了n个皇后,说明找到一个解if row == n:result.append(["".join(row) for row in board])returnfor col in range(n):# 检查当前列和对角线是否有皇后if col in cols or (row - col) in diag1 or (row + col) in diag2:continue  # 如果有冲突,跳过当前列# 放置皇后board[row][col] = "Q"# 标记当前列和对角线cols.add(col)diag1.add(row - col)diag2.add(row + col)# 递归处理下一行backtrack(row + 1)# 回溯,删除当前位置的皇后,并清理列和对角线的标记board[row][col] = "."cols.remove(col)diag1.remove(row - col)diag2.remove(row + col)backtrack(0)

return result
4.6 贪心算法
4.6.1 概述
贪心算法在解决问题时,采取的是逐步选择当前状态下最优的选项(即局部最优解),并期望通过这些局部最优解得到全局最优解。在每一步中,贪心算法都会选择当前看起来最优的选择,不考虑未来的选择。并通过一系列局部最优的选择,最终达到全局最优解(虽然并非总是能得到最优解,贪心算法的有效性依赖于问题的特性)。
贪心算法的特点:
 选择性:在每一步选择中,贪心算法根据某种启发式策略选择局部最优解。
 不可回溯:一旦做出了选择,就不能回退或重新考虑。
 局部最优:每一步的选择都依赖于局部最优,但并不保证整个问题能得到全局最优解。
贪心算法能够得到全局最优解的条件是问题需要满足贪心选择性质和最优子结构:
 贪心选择性质:通过局部最优的选择可以导出全局最优解。也就是说,每一步的局部选择都不会影响后续的选择,最终可以得到全局最优。
 最优子结构:问题的最优解包含子问题的最优解,即可以通过解决子问题来构建问题的最终解。
4.6.2 案例一:最大交换
力扣670题https://leetcode.cn/problems/maximum-swap/description/
现有一个非负整数,至多可以交换一次数字中的任意两位。返回能得到的最大值。
示例:
 输入:2736
 输出:7236
解释:交换数字2和数字7。
1)思路分析
从右向左遍历,同时维护一个最大数的索引。
 如果当前位置的数大于最大数,则更新最大数索引。
 否则将当前位置的数与最大数进行交换,交换后的数更新到result中,再将两个位置的数交换回来将数组恢复原样。
遍历结束后,result中的数就是能得到的最大值。
def maximumSwap(num):
result = num
num_list = list(str(num))
max_index = -1 # 最大值的索引
for i in range(len(num_list) - 1, -1, -1):
# 当前值大于最大值时,更新最大值的索引
if num_list[i] > num_list[max_index]:
max_index = i
# 当前值小于最大值时,交换,更新result,再交换回来
else:
num_list[i], num_list[max_index] = num_list[max_index], num_list[i]
result = max(result, int(“”.join(num_list)))
num_list[i], num_list[max_index] = num_list[max_index], num_list[i]
return result
4.6.3 案例二:分发糖果
力扣135题https://leetcode.cn/problems/candy/description/
n个孩子站成一排。用一个整数数组ratings表示每个孩子的评分。按照以下要求,给这些孩子分发糖果:
 每个孩子至少分配到1个糖果。
 相邻两个孩子评分更高的孩子会获得更多的糖果。
给每个孩子分发糖果,计算并返回需要准备的最少糖果数目。
1)方法一
每个孩子先分发1个糖果。
从左向右遍历,如果右边孩子比左边孩子评分高,则右边孩子糖果数量应该>左边孩子糖果数量,这时令右边孩子糖果数量为左边孩子糖果数量+1。
再从右向左遍历,如果左边孩子比右边孩子评分高,则左边孩子糖果数量应该为max(右边孩子糖果数量+1, 自己糖果数量)。
def candy(ratings):
n = len(ratings)

# 每个孩子先分发1个糖果
candy_num = [1] * len(ratings)# 从左向右遍历,如果右边评分更高,则右边孩子的糖果数改为左边孩子的糖果数+1
for pos in range(n - 1):if ratings[pos] < ratings[pos + 1]:candy_num[pos + 1] = candy_num[pos] + 1# 从右向左遍历,如果左边评分更高,则左边孩子的糖果数改为右边孩子的糖果数+1
total_candies = candy_num[-1]
for pos in range(n - 2, -1, -1):if ratings[pos] > ratings[pos + 1]:if candy_num[pos] <= candy_num[pos + 1]:candy_num[pos] = candy_num[pos + 1] + 1total_candies += candy_num[pos]
return total_candies

2)方法二
每个孩子先分发1个糖果。
按孩子评分相较于前一个孩子评分的增加、减少、不变分成3个区域,分别是上升区、下降区、平缓区。

在进入不同区域时,执行不同的操作:
 上升区
上升区长度+1,并清空之前的下降区长度。同时在result中累加糖果数。上升区或下降区长度每增加1,result中都需要增加与上升区或下降区长度相同数量的糖果。

 下降区
下降区存在一个特殊的准下降区。当从上升区进入下降区后,第一个进入的为准下降区。
准下降区不计入下降区长度。
当下降区长度等于上升区长度时,准下降区转变为真下降区并计入下降区长度。
下降区内清空之前的上升区长度,同时在result中累加糖果数。

 平缓区
清空所有记录,没有其他操作。
def candy(ratings):
# 每个孩子分发一个糖果
result = len(ratings)
# 上升区长度
up_length = 0
# 上升区长度的记录
up_num = 0
# 下降区长度
down_length = 0
for i in range(1, len(ratings)):
# 如果处于上升区
if ratings[i] > ratings[i - 1]:
# 上升区长度+1,清空下降区长度,并在result中累加糖果数
up_length += 1
up_num = up_length
down_length = 0
result += up_length
# 如果处于下降区
elif ratings[i] < ratings[i - 1]:
# 如果上升区长度为0,说明前一个位置已经不在上升区内,下降区长度+1
if up_length == 0:
down_length += 1
# 如果下降区长度已经等于之前上升区长度,说明峰值的糖果数由下降区决定,下降区长度+1
if down_length == up_num:
down_length += 1
# 清空上升区长度
up_length = 0
result += down_length
# 如果处于平缓区
else:
# 清空所有记录
up_length = 0
down_length = 0
up_num = 0
return result

相关文章:

AI大模型从0到1记录学习 数据结构和算法 day20

4.3 分治算法 4.3.1 概述 分治算法的基本思想为&#xff1a;将原问题递归的分解为若干个&#xff08;通常是两个以上&#xff09;规模较小、相互独立且性质相同的子问题&#xff0c;直到子问题足够简单&#xff0c;简单到可以直接求解。然后再返回结果&#xff0c;逐个解决上层…...

面阵相机中M12镜头和远心镜头的区别及性能优势

以下是关于面阵相机中M12镜头和远心镜头的区别及性能优势的详细分析&#xff0c;结合知识库内容整理如下&#xff1a; 一、M12镜头与远心镜头的核心区别 1. 设计原理与光学特性 特性M12镜头远心镜头光学设计标准镜头设计&#xff0c;无特殊光学校正&#xff0c;依赖传统光路。…...

[创业之路-385]:企业法务 - 初创公司如何做好商业秘密的管理

一、商业秘密的定义与价值 定义&#xff1a; 商业秘密是企业的核心资产&#xff0c;包括技术信息&#xff08;如算法、配方&#xff09;和经营信息&#xff08;如客户名单、定价策略&#xff09;&#xff0c;具有非公开性、商业价值、保密性三大特征。价值&#xff1a; 初创公…...

Qt5.15.2+OpenCV4.9.0开发环境搭建详细图文教程(OpenCV使用Qt自带MinGW编译的全过程,包教包会)

【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C++语言开发基础总结》 《从0到1学习嵌入式Linux开发》 《QT开发实战》 《Android开发实战》 《实用硬件方案设计》 《结构建模设…...

怎么实现RAG检索相似文档排序:similarities

怎么实现RAG检索相似文档排序:similarities top_5_indices = similarities.argsort()[-5:][::-1] 这行代码的作用是从一组相似度得分中获取相似度最高的5个元素的索引。 similarities:这是一个包含了某个问题与所有文档之间余弦相似度得分的一维数组(假设 similarities 是通…...

NLP高频面试题(五十三)——深度学习正则化详解

一、动因篇 为什么要正则化? 深度神经网络通常包含数以万计甚至数以亿计的参数,模型容量极大,极易在有限的训练数据上“记住”噪声与异常样本,从而出现过拟合(overfitting)现象。过拟合导致模型在训练集上表现优异,但在测试集或真实场景中泛化能力大幅下降。正则化(r…...

2.idea查看某个类的方法名称和实现

2.idea查看某个类的方法名称和实现 ctrl鼠标左键单击类名 点击侧边栏Structure可看到方法名称的统计&#xff0c;这样直观...

FeignClient用法笔记

1. FeignClient简介 在微服务架构中总需要各个服务相互调用&#xff0c;各个服务又是以接口方式暴露&#xff0c;所以需要Http远程调用&#xff1b;为了简化调用&#xff0c;Spring Cloud OpenFeign 库提供了org.springframework.cloud.openfeign.FeignClient 注解&#xff1a…...

【Redis】 Redis中常见的数据类型(二)

文章目录 前言一、 List 列表1. List 列表简介2.命令3. 阻塞版本命令4. 内部编码5. 使用场景 二、Set 集合1. Set简单介绍2. 普通命令3 . 集合间操作4. 内部编码5. 使用场景 三、Zset 有序集合1.Zset 有序集合简介2. 普通命令3. 集合间操作4. 内部编码5. 使用场景 结语 前言 在…...

电力作业安全工器具全解析:分类、配置与检查要点

在电力行业&#xff0c;每一次作业都面临潜在危险&#xff0c;安全工器具是保障作业人员生命安全的关键。今天&#xff0c;金能电力带大家深入了解电力作业中常见的安全工器具&#xff0c;以及它们的检查与使用要点。 电力作业中安全工器具种类繁多。绝缘安全工器具因直接关联带…...

PowerBI-使用参数动态修改数据源路径

PowerBI-使用参数动态修改数据源路径 在PowerQuery中可以使用参数&#xff0c;通过参数我们可以将多个文件路径相同的字符串进行替换。 以一个案例分享下过程&#xff1a; 第一步&#xff0c;导入一个含有多个sheet表的EXCEL工作薄&#xff0c;点击转换数据&#xff0c;如图…...

Temperature

模型中Temperature参数的详细解释 ​​Temperature​​ 是生成模型&#xff08;如GPT、LLaMA等&#xff09;中用于控制输出多样性和随机性的关键超参数。它通过调整模型预测概率分布的平滑程度&#xff0c;直接影响生成文本的创造性与稳定性。 模型中Temperature参数的详细解…...

C++ 日志系统实战第二步:不定参数函数解析

全是通俗易懂的讲解&#xff0c;如果你本节之前的知识都掌握清楚&#xff0c;那就速速来看我的项目笔记吧~ 相关技术知识补充 不定参宏函数 在 C 语言中&#xff0c;不定参宏函数是一种强大的工具&#xff0c;它允许宏接受可变数量的参数&#xff0c;类似于不定参函数&#…...

【高并发】 MySQL锁优化策略

在数据库高并发场景中&#xff0c;行锁、表锁和高并发处理是密切相关的概念&#xff0c;它们共同影响着系统的并发性能和数据一致性。以下是三者的详细解释及高并发处理的策略&#xff1a; 1. 行锁&#xff08;Row-Level Locking&#xff09; 行锁是数据库中最小的锁粒度&…...

C语言——填充矩阵

C语言——填充矩阵 一、问题描述二、格式要求1.输入形式2.输出形式3.样例 三、实验代码 一、问题描述 编程实现自动填充nn矩阵元素数值&#xff0c;填充规则为&#xff1a;从第一行最后一列矩阵元素开始按逆时针方向螺旋式填充数值1&#xff0c;2&#xff0c;…&#xff0c;nn…...

CSS3 基础(背景-文本效果)

二、背景效果 属性功能示例值说明background设置背景颜色或渐变background: linear-gradient(45deg, #4CAF50, #FF5722);设置背景颜色、图片或渐变效果。background-size调整背景图片大小background-size: cover;设置背景图片的显示大小&#xff0c;如 cover 或 contain。back…...

点云配准算法之NDT算法原理详解

一、算法概述 NDT&#xff08;Normal Distributions Transform&#xff09;最初用于2D激光雷达地图构建&#xff08;Biber & Straer, 2003&#xff09;&#xff0c;后扩展为3D点云配准。它将点云数据空间划分为网格单元&#xff08;Voxel&#xff09;&#xff0c;在每个体…...

springboot在eclipse里面运行 run as 是Java Application还是 Maven

在 Eclipse 里运行 Spring Boot 项目时&#xff0c;既可以选择以“Java Application”方式运行&#xff0c;也可以通过 Maven 命令来运行&#xff0c;下面为你详细介绍这两种方式及适用场景。 以“Java Application”方式运行 操作步骤 在项目中找到带有 SpringBootApplicat…...

Redis 基础和高级用法入门

redis 是什么&#xff1f; Redis是一个远程内存数据库&#xff0c;它不仅性能强劲&#xff0c;而且还具有复制特性以及为解决问题而生的独一无二的数据模型。Redis提供了5种不同类型的数据结构&#xff0c;各式各样的问题都可以很自然地映射到这些数据结构上&#xff1a…...

使用vue2开发一个在线旅游预订平台-前端静态网站项目练习

hello,大家好&#xff0c;今天给大家再分享一个前端vue2练习项目-在线旅游预订平台。我们在学习编程的时候&#xff0c;除了学习编程的基础知识&#xff0c;为了让我们快速的掌握一门编程技术&#xff0c;肯定离不开各种项目的练习&#xff0c;今天分享的这个前端练习项目&…...

Ext Direct 功能与使用详解

Ext Direct 是 Ext JS 框架中的一个功能模块,旨在简化前端 JavaScript 应用与后端服务器之间的通信。其核心思想是通过远程过程调用(RPC)协议,将服务器端的方法透明地映射为前端可直接调用的 JavaScript 函数,从而减少手动编写 Ajax 请求和处理响应的代码量。 一、Ext Dir…...

Android移动应用开发入门示例:Activity跳转界面

介绍如何使用LinearLayout布局实现基本的UI设计&#xff0c;并实现两个Activity之间的跳转&#xff0c;适合刚接触Android Studio的新手学习。我们将使用Java语言开发&#xff0c;布局采用XML文件。以下为完整源码与运行说明&#xff1a; 案例前的准备工作&#xff1a; 1.1XM…...

【hadoop】HBase分布式数据库安装部署

一、HBase集群的安装与配置 步骤&#xff1a; 1、使用XFTP将HBase安装包hbase-1.2.0-bin.tar.gz发送到master机器的主目录。 2、解压安装包&#xff1a; tar -zxvf ~/hbase-1.2.0-bin.tar.gz 3、修改文件夹的名字&#xff0c;将其改为hbase&#xff0c;或者创建软连接也可…...

理解npm的工作原理:优化你的项目依赖管理流程

目录 什么是npm npm核心功能 npm 常用指令及其作用 执行npm i 发生了什么? 1. 解析命令与参数 2. 检查依赖文件 3. 依赖版本解析与树构建 4. 缓存检查与包下载 5. 解压包到 node_modules 6. 更新 package-lock.json 7. 处理特殊依赖类型 8. 执行生命周期脚本 9. …...

【Python笔记 04】输入函数、转义字符

一、Input 输入函数 prompt是提示&#xff0c;会在控制台显示&#xff0c;用作提示函数。 name input("请输入您的姓名&#xff1a;") print (name)提示你输入任意信息&#xff1a; 输入input test后回车&#xff0c;他输出input test 二、常用的转义字符 只讲…...

MySQL数据库基本操作-DQL-基本查询

数据库的操作中&#xff0c;查询是最重要的 一、基本查询-数据准备 -- 数据准备 create database if not exists mydb2; use mydb2; create table product( pid int primary key auto_increment, pname varchar(20) not null, price double, category_id varchar(20) …...

13、性能优化:魔法的流畅之道——React 19 memo/lazy

一、记忆封印术&#xff08;React.memo&#xff09; 1. 咒语本质 "memo是时间转换器的记忆晶石&#xff0c;冻结无意义的能量波动&#xff01;" 通过浅层比较&#xff08;shallowCompare&#xff09;或自定义预言契约&#xff0c;阻止组件在props未变时重新渲染。 …...

低代码平台开发手机USB-HID调试助手

项目介绍 USB-HID调试助手是一种专门用于调试和测试USB-HID设备的软件工具。USB-HID设备是一类通过USB接口与计算机通信的设备&#xff0c;常见的HID设备包括键盘、鼠标、游戏控制器、以及一些专用的工业控制设备等。 主要功能包括&#xff1a; 数据监控&#xff1a;实时监控和…...

Langchain_Agent+数据库

本处使用Agent数据库&#xff0c;可以直接执行SQL语句。可以多次循环查询问题 前文通过chain去联系数据库并进行操作&#xff1b; 通过链的不断内嵌组合&#xff0c;生成SQL在执行SQL再返回。 初始化 import os from operator import itemgetterimport bs4 from langchain.ch…...

Code Splitting 分包策略

以下是关于分包策略(Code Splitting)的深度技术解析,涵盖原理、策略、工具实现及优化技巧: 一、分包核心价值与底层原理 1. 核心价值矩阵 维度未分包场景合理分包后首屏速度需加载全部资源仅加载关键资源缓存效率任意修改导致全量缓存失效按模块变更频率分层缓存并行加载单…...

AI 开发入门之 RAG 技术

目录 一、从一个简单的问题开始二、语言模型“闭卷考试”的困境三、RAG 是什么—LLM 的现实世界“外挂”四、RAG 的七步流程第一步&#xff1a;加载数据&#xff08;Load&#xff09;第二步&#xff1a;切分文本&#xff08;Chunking&#xff09;第三步&#xff1a;向量化&…...

day36图像处理OpenCV

文章目录 一、图像预处理18 模板匹配18.1模板匹配18.2 匹配方法18.2.1 平方差匹配18.2.2 归一化平方差匹配18.2.3 相关匹配18.2.4 归一化相关匹配18.2.5 相关系数匹配18.2.6 归一化相关系数匹配 18.3 绘制轮廓18.4案例 一、图像预处理 18 模板匹配 18.1模板匹配 模板匹配就是…...

系统与网络安全------弹性交换网络(3)

资料整理于网络资料、书本资料、AI&#xff0c;仅供个人学习参考。 STP协议 环路的危害 单点故障 PC之间的互通链路仅仅存在1个 任何一条链路出现问题&#xff0c;PC之间都会无法通信 解决办法 提高网络可靠性 增加冗余/备份链路 增加备份链路后交换网络上产生二层环路 …...

FPGA上实现YOLOv5的一般过程

在FPGA上实现YOLOv5 YOLO算法现在被工业界广泛的应用&#xff0c;虽说现在有很多的NPU供我们使用&#xff0c;但是我们为了自己去实现一个NPU所以在本文中去实现了一个可以在FPGA上运行的YOLOv5。 YOLOv5的开源代码链接为 https://github.com/ultralytics/yolov5 为了在FPGA中…...

verilog和system verilog常用数据类型以及常量汇总

int和unsigned 在 Verilog-2001 中&#xff0c;没有 int 和 unsigned 这样的数据类型。这些关键字是 SystemVerilog 的特性&#xff0c;而不是 Verilog-2001 的一部分。 Verilog-2001 的数据类型 在 Verilog-2001 中&#xff0c;支持的数据类型主要包括以下几种&#xff1a; …...

wordpress学习笔记

P1 P2 P3...

Rust 学习笔记:编程语言的相关概念

Rust 学习笔记&#xff1a;编程语言的相关概念 Rust 学习笔记&#xff1a;编程语言的相关概念动态类型 vs 静态类型动态类型 (Dynamically Typed)静态类型 (Statically Typed)对比示例 强类型 vs 弱类型强类型 (Strongly Typed)弱类型 (Weakly Typed)对比示例 编译型语言 vs 解…...

react nativeWebView跨页面通信

场景 react native项目里&#xff0c;有一些移动端的应用喜欢使用h5来开发&#xff0c;会出现需要跨tab和跨页面通信的场景&#xff0c;可以使用pubsub-js来实现通信。 实现思路 在react native 层实现pubsub的公共API&#xff0c;提供订阅消息、发布消息、取消订阅接口&…...

Python爬虫(3)HTML核心技巧:从零掌握class与id选择器,精准定位网页元素

目录 一、背景与意义‌二、class与id的基础概念与语法规则‌2.1 什么是class与id&#xff1f;‌2.2 核心区别总结 三、应用场景与实战案例‌3.1 场景1&#xff1a;CSS样式管理‌3.2 场景2&#xff1a;JavaScript交互‌3.3 场景3&#xff1a;SEO优化与语义化‌ 四、常见误区与最…...

BGE(BAAI General Embedding)模型详解

BGE&#xff08;BAAI General Embedding&#xff09;模型详解 BGE&#xff08;BAAI General Embedding&#xff09;是北京智源人工智能研究院&#xff08;BAAI&#xff09;推出的通用文本嵌入模型系列&#xff0c;旨在为各种自然语言处理任务提供高质量的向量表示。 一、BGE模…...

【Linux网络】应用层自定义协议与序列化及Socket模拟封装

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…...

Rust项目GPG签名配置指南

Rust项目GPG签名配置指南 一、环境准备 # 安装Gpg4win&#xff08;Windows&#xff09; winget install -e --id GnuPG.Gpg4win二、密钥生成与配置 # 生成RSA4096密钥 gpg --full-generate-key # 类型选RSA and RSA&#xff0c;长度4096&#xff0c;邮箱填z3266420686202216…...

6.第六章:数据分类的技术体系

文章目录 6.1 数据分类的技术架构6.1.1 数据分类的整体流程6.1.2 数据分类的技术组件6.1.2.1 数据采集与预处理6.1.2.2 特征工程与选择6.1.2.3 分类模型构建6.1.2.4 模型评估与优化6.1.2.5 分类结果应用与反馈 6.2 数据分类的核心技术与算法6.2.1 传统机器学习算法6.2.2 深度学…...

Nginx 反向代理,啥是“反向代理“啊,为啥叫“反向“代理?而不叫“正向”代理?它能干哈?

Nginx 反向代理的理解与配置 User 我打包了我的前端vue项目&#xff0c;上传到服务器&#xff0c;在宝塔面板安装了nginx服务&#xff0c;配置了文件 nginx.txt .运行了项目。 我想清楚&#xff0c;什么是nginx反向代理&#xff1f;是nginx作为一个中介&#xff1f;中间件来集…...

下篇:深入剖析 BLE GATT / GAP / SMP 与应用层(约5000字)

引言 在 BLE 协议栈的最上层,GAP 定义设备角色与连接管理,GATT 构建服务与特征,SMP 负责安全保障,应用层则承载具体业务逻辑与 Profile。掌握这一层,可实现安全可靠的设备发现、配对、服务交互和定制化业务。本文将详解 GAP、GATT、SMP 三大模块,并通过示例、PlantUML 时…...

Linux Awk 深度解析:10个生产级自动化与云原生场景

看图猜诗&#xff0c;你有任何想法都可以在评论区留言哦~ 摘要 Awk 作为 Linux 文本处理三剑客中的“数据工程师”&#xff0c;凭借字段分割、模式匹配和数学运算三位一体的能力&#xff0c;成为处理结构化文本&#xff08;日志、CSV、配置文件&#xff09;的终极工具。本文聚…...

无人设备遥控之调度自动化技术篇

无人设备遥控器的调度自动化技术是现代科技发展的重要成果&#xff0c;它通过集成先进的通信、控制、传感器及人工智能技术&#xff0c;实现了对无人设备的高效、精准调度与自动化管理。 一、核心技术 无线通信技术 调度自动化依赖于高速、稳定的无线通信网络&#xff08;如5…...

STM32F407 HAL库使用 DMA_Normal 模式实现 UART 循环发送(无需中断)

在 STM32 开发中&#xff0c;很多人喜欢使用 DMA 来加速串口发送数据。然而&#xff0c;默认的 DMA 往往配合中断或使用循环模式&#xff08;DMA_CIRCULAR&#xff09;使用。但在某些特定需求下&#xff0c;我们希望&#xff1a; 使用 DMA_NORMAL 模式&#xff0c;确保 DMA 每次…...

汽车自动驾驶介绍

0 Preface/Foreword 1 介绍 1.1 FSD FSD: Full Self-Driving&#xff0c;完全自动驾驶 &#xff08;Tesla&#xff09; 1.2 自动驾驶级别 L0 - L2&#xff1a;辅助驾驶L3&#xff1a;有条件自动驾驶L4/5 &#xff1a;高度/完全自动驾驶...

Uniapp-小程序从入门到精通

沉淀UNIAPP项目精华模版 ******************************************************************************************************************************************* 1、数据库的导入SQL **************************************************************************…...