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

面试算法高频04-分治与回溯

分治与回溯

分治和回溯算法,包括其概念、特性、代码模板,并结合具体题目进行讲解,旨在帮助学员理解和掌握这两种算法的应用。

  1. 分治与回溯的概念
    • 分治(Divide & Conquer):本质上基于递归,先将问题分解为多个子问题(Divide),分别求解子问题(Conquer),再将子问题的解合并(Merge)得到原问题的解 。以抛硬币问题为例帮助理解,通过不断将问题细分来简化求解过程。
    • 回溯(Backtracking):采用试错思想,尝试分步解决问题。在分步过程中,若当前分步答案无法得到正确解答,则取消上一步或上几步计算,通过其他可能的分步解答继续尝试。它通常用简单递归实现,可能找到正确答案,也可能在尝试所有分步方法后宣告问题无解,最坏情况下时间复杂度为指数时间。
  2. 分治算法
    • 代码模板:包含递归终止条件判断、数据准备、问题分解、子问题求解和结果合并等步骤。通过divide_conquer函数模板展示,在递归终止条件中判断问题是否为空,若为空则打印结果并返回;准备数据后将问题拆分为子问题,递归调用函数求解子问题,最后处理并生成最终结果 。
    • 理解要点:代码结构与递归相似,可看作在递归基础上增加了问题分解和结果合并步骤,有助于将复杂问题逐步简化解决。
  3. 回溯算法
    • 代码示例 - 括号生成:在力扣22题括号生成中,通过_generate递归函数实现回溯。利用leftright分别记录左括号和右括号的使用数量,在递归过程中根据条件添加括号,当leftright都等于给定对数n时,将生成的括号组合加入结果列表 。
    • 算法理解:在解决问题时,通过不断尝试不同的分步选择,当发现当前选择无法得到有效答案时,回退到上一步重新选择,直至找到正确答案或确定问题无解。

练习题

括号生成

题目复述

题目要求是,给定一个整数 nn 代表着括号的对数。任务是编写一个函数,这个函数要能够生成所有可能的、并且是有效的括号组合。这里的有效是指在任意前缀中左括号的数量都不少于右括号的数量,且最终左、右括号的数量都等于 n 。举例来说,当 n = 3 时,生成的结果应该是像 ["((()))", "(()())", "(())()", "()(())", "()()()"] 这样的一系列有效的括号组合。

Python代码
from typing import Listclass Solution:def generateParenthesis(self, n: int) -> List[str]:result = []def _generate(left, right, s):# terminatorif left == n and right == n:result.append(s)return# drill downif left < n:_generate(left + 1, right, s + "(")if left > right:_generate(left, right + 1, s + ")")_generate(0, 0, "")return result
代码解析
  1. 整体结构:定义了 Solution 类,其中 generateParenthesis 方法是对外提供功能的接口,接收整数 n 作为参数,返回值类型是字符串列表,即所有有效的括号组合。在 generateParenthesis 方法内部,又定义了一个局部函数 _generate ,它采用递归的方式来逐步生成括号组合。同时初始化了一个空列表 result ,用于存储最终有效的括号组合。
  2. 递归终止条件(terminator):在 _generate 函数中,通过判断 if left == n and right == n: 来确定是否达到递归终止条件。当左括号的数量 left 和右括号的数量 right 都等于给定的 n 时,说明已经成功构建出了一个完整且有效的括号组合,此时将这个组合字符串 s 添加到结果列表 result 中,然后通过 return 语句结束当前这一支递归调用。
  3. 处理当前逻辑并递归深入(drill down)
    • 添加左括号:使用条件 if left < n: 进行判断,只要左括号的数量 left 还小于给定的 n ,就表示还可以继续添加左括号。此时通过递归调用 _generate(left + 1, right, s + "(") ,将左括号数量增加1 ,并把左括号字符 ( 添加到当前正在构建的括号组合字符串 s 后面,继续深入递归以进一步构建括号组合。
    • 添加右括号:利用条件 if left > right: 进行判断,当左括号的数量 left 大于右括号的数量 right 时,意味着可以添加右括号(这是为了保证在构建括号组合的任意时刻,左括号的数量都不少于右括号的数量,从而保证组合的有效性 )。通过递归调用 _generate(left, right + 1, s + ")") ,将右括号数量增加1 ,并把右括号字符 ) 添加到当前的括号组合字符串 s 后面,继续递归构建括号组合。
  4. 返回结果:在 generateParenthesis 方法中,调用 _generate(0, 0, "") 开始递归构建括号组合的过程,当递归结束后,直接返回存储着所有有效括号组合的 result 列表。
复杂度分析
  • 时间复杂度:该算法的时间复杂度大致为 O ( 4 n / n ) O(4^n / \sqrt{n}) O(4n/n ) 。从解空间角度来看,对于 n 对括号,其所有可能的组合数量规模大致符合这样的数量级。虽然在递归过程中通过条件判断(左括号数量和右括号数量的约束 )减少了一些无效分支的计算,但整体数量级仍然是这个范围。
  • 空间复杂度:递归调用栈的深度最大为 2n (因为最多会有 n 个左括号和 n 个右括号依次入栈 ),所以仅考虑递归栈的空间占用时,空间复杂度为 O ( n ) O(n) O(n) 。再考虑到结果列表 result ,在最坏情况下它存储的有效括号组合数量为卡特兰数 O ( C 2 n n ) O(C_{2n}^n) O(C2nn) ,每个组合的长度为 2n ,综合起来整个算法的空间复杂度为 O ( 4 n / n ) O(4^n / \sqrt{n}) O(4n/n )

题目描述

实现 pow(x, n) ,也就是计算 xn 次幂函数(即 x n x^n xn )。题目给定了相关约束条件:-100.0 < x < 100.0n 是 32 位有符号整数,数值范围在 [−2^31, 2^31 − 1] 。同时给出了示例:

  • 示例 1 中,输入 x = 2.00000, n = 10 ,输出 1024.00000
  • 示例 2 里,输入 x = 2.10000, n = 3 ,输出 9.26100
  • 示例 3 时,输入 x = 2.00000, n = -2 ,输出 0.25000 ,因为 2^(-2) = 1/2^2 = 1/4 = 0.25

Python代码和解析

暴力解法

class Solution:def myPow(self, x: float, n: int) -> float:if n == 0:return 1elif n < 0:x = 1 / xn = -nresult = 1for _ in range(n):result *= xreturn result

解析:先处理特殊情况,当 n 为 0 ,任何数的 0 次幂是 1 ,直接返回 1 。若 n 为负,将 x 取倒数,n 变为正。然后通过 for 循环,让 result 连乘 nx 得到结果。时间复杂度为 O ( n ) O(n) O(n) ,因为要进行 n 次乘法;空间复杂度 O ( 1 ) O(1) O(1) ,只用到几个固定变量。

分治算法

class Solution:def myPow(self, x: float, n: int) -> float:if n == 0:return 1elif n < 0:x = 1 / xn = -nreturn self.helper(x, n)def helper(self, x, n):if n == 0:return 1half = self.helper(x, n // 2)if n % 2 == 0:return half * halfelse:return half * half * x

解析:同样先处理 n 为 0 和负数情况。helper 递归函数用分治思想,把求 xn 次幂问题分解成求 xn//2 次幂问题。若 n 是偶数,x^n = (x^(n//2)) * (x^(n//2)) ;若 n 是奇数,x^n = (x^(n//2)) * (x^(n//2)) * x 。时间复杂度 O ( l o g n ) O(log n) O(logn) ,每次递归问题规模减半;空间复杂度 O ( l o g n ) O(log n) O(logn) ,递归调用栈深度最大为 O ( l o g n ) O(log n) O(logn)

分治 + 迭代

class Solution:def myPow(self, x: float, n: int) -> float:if n < 0:x = 1 / xn = -nresult = 1current_product = xwhile n > 0:if n % 2 == 1:result *= current_productcurrent_product *= current_productn = n // 2return result

解析:先处理 n 为负的情况。初始化 result 为 1 ,current_productx 。循环中,通过 n % 2 检查 n 的二进制位,为 1 就把 current_product 乘到 result 中,接着 current_product 平方,n 右移一位(除以 2 ),直到 n 为 0 。时间复杂度 O ( l o g n ) O(log n) O(logn) ,循环次数是 n 二进制表示的位数;空间复杂度 O ( 1 ) O(1) O(1) ,只用了几个固定变量。
在二进制幂次计算里,一个整数的幂次计算可以转化为对其二进制表示的处理。以计算 x n x^n xn为例,将 n n n用二进制表示后,每一位都对应着不同的 x x x的幂次。

  • 例如计算 x 13 x^{13} x13 13 13 13的二进制是 1101 1101 1101 x 13 = x 8 + 4 + 1 = x 8 × x 4 × x 1 x^{13}=x^{8 + 4 + 1}=x^8\times x^4\times x^1 x13=x8+4+1=x8×x4×x1 。从右往左看二进制位,第一位是 1 1 1,代表 x 1 x^1 x1;第二位是 0 0 0,代表没有 x 2 x^2 x2 ;第三位是 1 1 1,代表 x 4 x^4 x4 ;第四位是 1 1 1,代表 x 8 x^8 x8
  • 回到代码中,while n > 0:循环每次处理 n n n的一个二进制位。if n % 2 == 1:判断当前处理的二进制位是否为 1 1 1,如果是,说明这个二进制位对应的 x x x的幂次需要乘到结果里。比如在计算 x 13 x^{13} x13时,当处理到第一位(从右往左)和第三位、第四位时,由于这些位是 1 1 1,所以要把对应的 x x x的幂次(即当前的current_product)乘到result中。而current_product在每次循环中会不断平方,依次对应 x 1 x^1 x1 x 2 x^2 x2 x 4 x^4 x4 x 8 x^8 x8等幂次。在计算 x 13 x^{13} x13时,第一次循环current_product x x x ,对应 x 1 x^1 x1 ,因为第一位是 1 1 1,所以result乘上 x x x ;第二次循环current_product变为 x 2 x^2 x2 ,但第二位是 0 0 0,不乘;第三次循环current_product变为 x 4 x^4 x4 ,第三位是 1 1 1result乘上 x 4 x^4 x4 ;第四次循环current_product变为 x 8 x^8 x8 ,第四位是 1 1 1result乘上 x 8 x^8 x8 。最终result的值就是 x 13 x^{13} x13 。 所以在二进制幂次计算中,奇数幂次(对应二进制位为 1 1 1的情况)需要额外乘上当前的底数,以此完成幂次的计算。

题目描述

给定一个整数数组 nums ,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。解集不能包含重复的子集,输出顺序可以任意。

最优解思路(位运算解法)
  1. 对于一个含有 n 个元素的集合,它的子集个数为 2 n 2^n 2n 个 。可以用二进制数来表示每个子集,从 0 2 n − 1 2^n - 1 2n1 2 n 2^n 2n 个二进制数,每一位对应集合中的一个元素,若该位为 1 ,表示对应元素在子集中;若为 0 ,表示对应元素不在子集中。
  2. 遍历从 0 2 n − 1 2^n - 1 2n1 的所有整数,对于每个整数,将其转换为二进制形式,根据二进制位的情况构建对应的子集。
代码实现(Python)
class Solution:def subsets(self, nums):n = len(nums)result = []for i in range(2 ** n):subset = []for j in range(n):if (i >> j) & 1:subset.append(nums[j])result.append(subset)return result
代码解析
  1. 确定子集数量范围
    • n = len(nums) 获取数组 nums 的长度。总共有 2 n 2^n 2n 个子集,所以通过 for i in range(2 ** n) 遍历从 0 2 n − 1 2^n - 1 2n1 的所有整数。
  2. 构建每个子集
    • 对于每个整数 i ,内部通过 for j in range(n) 遍历 nums 数组的每个元素位置。(i >> j) & 1 用于判断 i 的二进制表示中第 j 位是否为 1i >> j 是将 i 的二进制表示右移 j 位,然后 & 1 是取最低位,如果结果为 1 ,说明第 j 位是 1 ,此时将 nums[j] 添加到当前子集 subset 中。
  3. 收集结果
    • 构建好一个子集 subset 后,将其添加到结果列表 result 中,最后返回 result
复杂度分析
  • 时间复杂度:外层循环执行 2 n 2^n 2n 次,内层循环对于每个外层循环执行 n 次,整体时间复杂度为 O ( n × 2 n ) O(n \times 2^n) O(n×2n) ,这是生成所有子集问题的理论最小时间复杂度。
  • 空间复杂度:除输入数组外,额外空间主要用于存储结果集。最坏情况下有 2 n 2^n 2n 个子集,假设每个子集平均长度为 n ,空间复杂度为 O ( n × 2 n ) O(n \times 2^n) O(n×2n)

前面我们提到一个含有(n)个元素的集合,其子集个数为(2^n)个,这可以通过二项式展开来理解,下面结合代码详细阐述。

二项式定理回顾

二项式定理的表达式为((a + b)^n=\sum_{k = 0}{n}C_{n}k a^{n - k}b{k}),其中(C_{n}k=\frac{n!}{k!(n - k)!}),它表示从(n)个不同元素中取出(k)个元素的组合数 。当(a = b = 1)时,((1 + 1)^n=\sum_{k = 0}{n}C_{n}k\times1^{n - k}\times1^{k}=\sum_{k = 0}{n}C_{n}k),也就是(2^n = C_{n}^0 + C_{n}1+C_{n}2+\cdots + C_{n}^n)。

代码逻辑与二项式展开的关联

以下是之前的代码:

class Solution:def subsets(self, nums):n = len(nums)result = []for i in range(2 ** n):subset = []for j in range(n):if (i >> j) & 1:subset.append(nums[j])result.append(subset)return result
1. 二项式展开各项含义
  • (C_{n}^k)表示从(n)个元素中选取(k)个元素的组合方式的数量。在集合的子集中,这就对应着含有(k)个元素的子集的个数。
  • 比如,对于一个有(n = 3)个元素的集合({a,b,c}):
    • (C_{3}^0)表示从(3)个元素中选(0)个元素的组合数,其值为(1),对应的子集就是空集(\varnothing)。
    • (C_{3}1)表示从(3)个元素中选(1)个元素的组合数,(C_{3}1=\frac{3!}{1!(3 - 1)!}=\frac{3!}{1!2!}=3),对应的子集为({a})、({b})、({c})。
    • (C_{3}2)表示从(3)个元素中选(2)个元素的组合数,(C_{3}2=\frac{3!}{2!(3 - 2)!}=\frac{3!}{2!1!}=3),对应的子集为({a,b})、({a,c})、({b,c})。
    • (C_{3}^3)表示从(3)个元素中选(3)个元素的组合数,其值为(1),对应的子集就是原集合({a,b,c})。
2. 代码中循环与二项式展开的对应关系
  • 外层循环for i in range(2 ** n),这里(2^n)就是二项式展开((1 + 1)n)的结果。从(0)到(2n-1)的每一个整数(i)都对应着集合的一个子集。这是因为每一个整数(i)的二进制表示可以用来确定集合中的哪些元素被选入子集中。
  • 内层循环for j in range(n)用于检查整数(i)的二进制表示的每一位。(i >> j) & 1 这个表达式用于判断(i)的第(j)位是否为(1),如果为(1),则将nums[j]添加到子集中。从二项式展开的角度看,当我们遍历所有的(i)时,实际上是在遍历所有可能的元素选取组合,也就是在遍历二项式展开中的每一项。
举例说明

假设nums = ['a', 'b', 'c'],(n = 3),(2^n=8)。

  • 当(i = 0)(二进制(000))时,内层循环中(i >> j) & 1对于所有(j)都为(0),得到子集(\varnothing),对应二项式展开中的(C_{3}^0)这一项。
  • 当(i = 1)(二进制(001))时,(i >> 0) & 1 = 1,将nums[0](即a)加入子集,得到子集({a});当(i = 2)(二进制(010))时,得到子集({b});当(i = 4)(二进制(100))时,得到子集({c}),这三个子集对应二项式展开中的(C_{3}^1)这一项。
  • 当(i = 3)(二进制(011))时,得到子集({a,b});当(i = 5)(二进制(101))时,得到子集({a,c});当(i = 6)(二进制(110))时,得到子集({b,c}),这三个子集对应二项式展开中的(C_{3}^2)这一项。
  • 当(i = 7)(二进制(111))时,得到子集({a,b,c}),对应二项式展开中的(C_{3}^3)这一项。

综上所述,代码通过遍历(0)到(2^n - 1)的所有整数,利用二进制位运算来确定元素的选取,从而得到集合的所有子集,这与二项式展开所表示的从(n)个元素中选取不同个数元素的组合情况是一一对应的,体现了集合子集个数与二项式展开结果(2^n)之间的紧密联系。

题目:多数元素(Majority Element)

链接:https://leetcode-cn.com/problems/majority-element/description/

题目描述

给定一个大小为n的数组nums,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊n / 2⌋的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

解法一:哈希表法
  1. 思路
    使用哈希表来记录每个元素出现的次数。遍历数组,对于每个元素,如果它已经在哈希表中,就将其对应的值(出现次数)加1;如果不在,就将其加入哈希表,出现次数初始化为1 。最后遍历哈希表,找出出现次数大于⌊n / 2⌋的元素。
  2. Python代码实现
class Solution:def majorityElement(self, nums):num_count = {}n = len(nums)for num in nums:num_count[num] = num_count.get(num, 0) + 1if num_count[num] > n // 2:return num
  1. 代码解释
    • 首先创建一个空的字典num_count用于存储元素及其出现次数,获取数组nums的长度n
    • 然后遍历数组nums,对于每个元素num,使用num_count.get(num, 0)获取num在字典中的出现次数(如果不存在则默认为0),并将其加1。
    • 每次更新完出现次数后,检查当前元素的出现次数是否大于n // 2,如果大于则直接返回该元素。
  2. 时间复杂度 O ( n ) O(n) O(n),其中n是数组nums的长度。遍历数组一次,哈希表的操作平均时间复杂度为常数,所以整体时间复杂度为 O ( n ) O(n) O(n)
  3. 空间复杂度 O ( n ) O(n) O(n),在最坏情况下,数组中的所有元素都不同,此时哈希表需要存储n个键值对,所以空间复杂度为 O ( n ) O(n) O(n)
解法二:排序法
  1. 思路
    先对数组进行排序,由于多数元素出现的次数大于⌊n / 2⌋,那么排序后数组中间位置(索引为n // 2)的元素必然是多数元素。
  2. Python代码实现
class Solution:def majorityElement(self, nums):nums.sort()return nums[len(nums) // 2]
  1. 代码解释
    • 使用nums.sort()对数组nums进行排序,Python的内置排序函数平均时间复杂度为 O ( n l o g n ) O(n log n) O(nlogn)
    • 排序后直接返回数组中间位置(索引为len(nums) // 2)的元素,该元素就是多数元素。
  2. 时间复杂度 O ( n l o g n ) O(n log n) O(nlogn),主要时间消耗在排序操作上,常见排序算法平均时间复杂度为 O ( n l o g n ) O(n log n) O(nlogn)
  3. 空间复杂度:如果使用的是原地排序算法(如Python的list.sort ),空间复杂度为 O ( 1 ) O(1) O(1);如果使用的是需要额外空间的排序算法(如归并排序),空间复杂度为 O ( n ) O(n) O(n)
解法三:摩尔投票法(最优解)
  1. 思路
    摩尔投票法的核心思想是通过两两抵消不同的元素,最后剩下的就是多数元素。维护一个候选元素candidate和它的计数值count。遍历数组,当count为0时,将当前元素设为candidate;如果当前元素与candidate相同,count加1,否则count减1 。遍历结束后,candidate即为多数元素。
  2. Python代码实现
class Solution:def majorityElement(self, nums):candidate = Nonecount = 0for num in nums:if count == 0:candidate = numcount += (1 if num == candidate else -1)return candidate
  1. 代码解释
    • 初始化候选元素candidateNone,计数值count为0。
    • 遍历数组nums,当count为0时,将当前元素num设为candidate。然后根据当前元素num是否与candidate相同,对count进行加1或减1操作。
    • 遍历结束后,candidate就是多数元素,直接返回。
  2. 时间复杂度 O ( n ) O(n) O(n),只需要遍历数组一次,时间复杂度为 O ( n ) O(n) O(n)
  3. 空间复杂度 O ( 1 ) O(1) O(1),只使用了常数级别的额外空间。

相关文章:

面试算法高频04-分治与回溯

分治与回溯 分治和回溯算法&#xff0c;包括其概念、特性、代码模板&#xff0c;并结合具体题目进行讲解&#xff0c;旨在帮助学员理解和掌握这两种算法的应用。 分治与回溯的概念 分治&#xff08;Divide & Conquer&#xff09;&#xff1a;本质上基于递归&#xff0c;先…...

整数编码 - 华为OD统一考试(A卷、C++)

题目描述 实现一种整数编码方法&#xff0c;使得待编码的数字越小&#xff0c;编码后所占用的字节数越小。 编码规则如下: 编码时7位一组&#xff0c;每个字节的低7位用于存储待编码数字的补码。字节的最高位表示后续是否还有字节&#xff0c;置1表示后面还有更多的字节&…...

对访问者模式的理解

对访问者模式的理解 一、场景二、不采用访问者模式1、代码2、特点 三、采用访问者模式1、代码2、特点 四、思考 一、场景 我们有一个图形系统&#xff0c;系统中有多种图形对象&#xff08;如圆形、方形等&#xff09;&#xff0c;每种图形对象都有不同的属性和行为。现在需要对…...

第三次PID状态机

以下是 apply_params 函数的实现步骤和代码示例&#xff1a; 1. 定义参数结构体 在头文件中定义 PID_Params 结构体&#xff0c;包含需要动态调整的 PID 参数&#xff1a; // ms_hal_photo_sensor.h typedef struct {float Kp; // 比例系数float Ki; // …...

如何在大型项目中有效使用TypeScript进行类型定义?

嗨&#xff0c;大家好&#xff0c;我是莫循&#xff0c;Typescript是JavaScript的超集&#xff0c;现在已经广泛用于前端开发&#xff0c;那么在项目中如何用好类型定义呢&#xff1f;以下是一些可以提供参考的案例实践。 一、类型组织策略 1. 模块化类型定义 按功能/模块划分…...

C4D XP 粒子动画云端渲染指南

在 C4D 动画制作领域&#xff0c;XP 粒子特效因其复杂的动力学计算常成为渲染瓶颈。传统本地渲染不仅耗时漫长&#xff0c;还需持续占用高配置硬件。而借助专业云渲染平台&#xff0c;创作者可突破物理限制&#xff0c;高效完成 XP 粒子动画的最终输出。 以渲染 101 平台为例&a…...

mysql知识总结 基础篇

Mysql知识总结 1. 执行一条sql语句 期间发生了什么&#xff1f;1. 如何查看mysql服务被多少个客户端链接了2. 空闲链接会一直闲置嘛&#xff1f;3. mysql的链接数量有限制嘛&#xff1f;4. 我们如何知道mysql要使用哪个索引5. 什么是覆盖索引 2. MySQL 一行记录是怎么存储的&am…...

基于条码数据生成校验密码的C++实现方案

前言 在医疗试剂、工业产品等需要严格追踪管理的领域&#xff0c;条码系统常被用于标识产品信息。本文将详细介绍4种用C实现的条码密码生成算法&#xff0c;这些算法可以根据条码前11位数据生成2位校验密码&#xff08;第9、10位&#xff09;&#xff0c;用于数据校验或简单防…...

前端工具方法整理

文章目录 1.在数组中找到匹配项&#xff0c;然后创建新对象2.对象转JSON字符串3.JSON字符串转JSON对象4.有个响应式对象&#xff0c;然后想清空所有属性5.判断参数不为空6.格式化字符串7.解析数组内容用逗号拼接 1.在数组中找到匹配项&#xff0c;然后创建新对象 const modifi…...

[数据结构]图krusakl算法实现

目录 Kruskal算法 Kruskal算法 我们要在连通图中去找生成树 连通图&#xff1a;在无向图中&#xff0c;若从顶点v1到顶点v2有路径&#xff0c;则称顶点v1与顶点v2是连通的。如果图中任意一对顶点都是连通的&#xff0c;则称此图为连通图。 生成树&#xff1a;一个连通图的最小…...

18-产品经理-跟踪进度

禅道是一个可以帮助产品经理跟踪研发进度的系统。通过禅道&#xff0c;产品经理可以从多个角度了解产品的研发状态。在仪表盘中&#xff0c;可以展示所有产品或单一产品的概况&#xff0c;包括需求、计划和发布数量&#xff0c;研发需求状态&#xff0c;Bug修复率和计划发布数。…...

华为机试—挑7

题目 你需要统计 1 到 n 之间与 7 有关的数字的个数。 与 7 有关的数字包括&#xff1a; 是 7 的倍数&#xff08;如 7,14,21 等&#xff09;&#xff1b;包含数字 7&#xff08;如 17,27,37,⋯ ,70,71,72,⋯等&#xff09;。 示例 输入&#xff1a;20 输出&#xff1a;3 说…...

【区块链安全 | 第三十四篇】合约审计之重入漏洞

文章目录 概念漏洞代码代码审计攻击代码攻击过程总结示例修复建议审计思路 概念 以太坊的智能合约可以互相调用&#xff0c;也就是说&#xff0c;一个合约可以调用另一个合约的函数。除了外部账户&#xff0c;合约本身也可以持有以太币并进行转账。当合约接收到以太币时&#…...

Java虚拟机——JVM(Java Virtual Machine)解析一

1.JVM是什么&#xff1f; 1.1 JVM概念 Java Virtual Machine (JVM) 是JDK的核心组件之一&#xff0c;它使得 Java 程序能够在任何支持 JVM 的设备或操作系统上运行&#xff0c;而无需修改源代码 JDK是什么&#xff0c;JDK和JVM是什么关系&#xff1f;1.Java IDE(Integrated …...

【JVM】question

问题 JVM线程是用户态还是内核态 java线程在jdk1.2之前&#xff0c;是基于名为“绿色线程”的用户线程实现的&#xff0c;这导致绿色线程只能同主线程共享CPU分片&#xff0c;从而无法利用多核CPU的优势。 由于绿色线程和原生线程比起来在使用时有一些限制&#xff0c; jdk1.2…...

页面编辑器CodeMirror初始化不显示行号或文本内容

延迟刷新 本来想延迟100毫秒的&#xff0c;但是会出现样式向左偏移的情况&#xff0c;于是试了试500毫秒&#xff0c;发现就没有问题了&#xff0c;可能是样式什么是需要一个加载过程吧。 useEffect(() > {editorRef.current?.setValue(value || );setTimeout(() > {edi…...

顺序表——C语言实现

目录 一、线性表 二、顺序表 1.实现动态顺序表 SeqList.h SeqList.c Test.c 问题 经验&#xff1a;free 出问题&#xff0c;2种可能性 解决问题 &#xff08;2&#xff09;尾删 &#xff08;3&#xff09;头插&#xff0c;头删 &#xff08;4&#xff09;在 pos 位…...

OpenCV 图形API(21)逐像素操作

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在OpenCV的G-API模块中&#xff0c;逐像素操作指的是对图像中的每个像素单独进行处理的操作。这些操作可以通过G-API的计算图&#xff08;Graph …...

车载联网终端4G汽车TBOX介绍定义与概述

汽车 TBOX&#xff08;Telematics Box&#xff09;是专为汽车设计的远程通信终端设备&#xff0c;属于车联网系统的关键组成部分。车联网系统一般包含主机、汽车 T - BOX、手机 APP 及后台系统。融合了车身网络和 4G 无线通信技术&#xff0c;为汽车提供丰富的 Telematics 服务…...

CentOS无法安装Vim文本编辑器问题以及解决方法

1.问题一&#xff1a;用户权限不够 解决方法一&#xff1a;切换到root用户 解决方法二&#xff1a;给本用户添加权限 2.问题二&#xff1a;镜像源问题&#xff1a;官方镜像源可能已经失效 解决方法&#xff1a; 1. 检查网络连接 2. 检查和配置 DNS 3. 更换镜像源&#…...

Kettle如何与应用集成

Kettle&#xff08;Pentaho Data Integration&#xff0c;PDI&#xff09;可以通过多种方式与应用程序集成&#xff0c;以下是7种主流方法及具体实现示例&#xff1a; 一、命令行调用&#xff08;最基础&#xff09; # 执行转换&#xff08;Transformation&#xff09; ./pan.…...

Pytorch torch.nn.utils.rnn.pad_sequence 介绍

torch.nn.utils.rnn.pad_sequence 是 PyTorch 中一个用于填充序列的实用函数&#xff0c;它主要用于处理长度不一的序列数据&#xff0c;将这些序列填充到相同的长度&#xff0c;以便能将它们组合成一个批量&#xff08;batch&#xff09;输入到神经网络中。以下是详细介绍&…...

4.7正则表达式

1.字符匹配 一般字符匹配自身. 匹配任意字符(换行符\n除外),一个点占一位\转义字符&#xff0c;使其后一个字符改变原来的意思(\.就是.)[......]字符集,对应的位置可以是字符集中的任意字符.字符集中的字符可以逐个列出,也可以给出范围如[abc]或[a-c] [^abc] 表示取反&#xf…...

CogPatInspectTool工具

CogPatInspectTool是康耐视中的一种模板比对的视觉检测工具&#xff0c;主要用于产品不良检测。其核心功能是通过将输入图像与预先训练好的模板进行对比&#xff0c;识别出两者之间的差异&#xff0c;并生成高亮差异图&#xff0c;从而判断产品是否存在缺陷。 效果图 CogPatIn…...

牛客周赛 + 洛谷刷题

秘藏 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N 200010; ll a[N], b[N]; int n, k; ll dp[2][N];//dp[i][j]是在i界中取了j之前的最大值 int main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);cin >> n >&…...

【数据结构】图论存储革新:十字链表双链设计高效解决有向图入度查询难题

十字链表 导读一、邻接表的优缺点二、十字链表2.1 结点结构2.2 原理解释2.2.1 顶点表2.2.2 边结点2.2.3 十字链表 三、存储结构四、算法评价4.1 时间复杂度4.2 空间复杂度 五、优势与劣势5.1 优势5.2 劣势5.3 特点 结语 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff…...

【JavaScript】十五、事件对象与环境对象

文章目录 1、事件对象1.1 获取事件对象1.2 常用属性1.3 案例&#xff1a;回车发布评论 2、环境对象this3、回调函数4、案例&#xff1a;tab切换5、案例&#xff1a;全选文本框&#x1f4d6; 1、事件对象 事件对象&#xff1a; 也是个对象&#xff0c;object&#xff0c;里面存…...

OJ--第N个泰波那契数列

1137. 第 N 个泰波那契数 - 力扣&#xff08;LeetCode&#xff09; 1 题干部分 2 拆解 1 状态表示&#xff1a;dp[i] 2 状态转移方程:dp[i]dp[i-1]dp[i-2]dp[i-3] 3 初始化:让dp[0]0,dp[1]dp[2]1 4 填表顺序:从dp[3]开始填从左往右填 5 返回值&#xff1a;dp[n]即为返回的…...

Python从入门到高手8.1节-元组类型详解

目录 8.1.1 理解元组类型 8.1.2 元组的类型名 8.1.3 元组的定义 8.1.4 元组的解包 8.1.5 元组是可迭代的 8.1.6 假期就这么结束了 8.1.1 理解元组类型 元组与列表有着相同的数据结构&#xff0c;区别在于&#xff0c;元组是不可变的数据类型&#xff0c;而列表是可变的数…...

使用 Qt 和 OBS 工具检测系统硬件编码器支持情况(NVENC、QSV、AMF)

在开发涉及视频处理的软件时,判断系统是否支持硬件加速编码器(如 NVIDIA NVENC、Intel QSV、AMD AMF)对于性能优化至关重要。本文将介绍如何结合 Qt 与 OBS Studio 附带的小工具程序,实现一个完整、异步且不会卡住 UI 的硬件加速检测模块。 一、背景与目标 硬件加速编码器…...

Python爬虫生成CSV文件的完整流程

引言 在当今数据驱动的时代&#xff0c;网络爬虫已成为获取互联网数据的重要工具。Python凭借其丰富的库生态系统和简洁的语法&#xff0c;成为了爬虫开发的首选语言。本文将详细介绍使用Python爬虫从网页抓取数据并生成CSV文件的完整流程&#xff0c;包括环境准备、网页请求、…...

图论:多源最短路

多源最短路 B3647 【模板】Floyd - 洛谷 #include<iostream> #include<cstring> using namespace std;const int N 110; int f[N][N]; int n, m;int main() {memset(f, 0x3f, sizeof(f));//对于重边的处理取较小值&#xff0c;所以要把全部都初始化成无穷大&…...

2024年已备案大模型发展趋势分析

2024年已备案大模型发展趋势分析 随着生成式人工智能技术的快速发展,其在各个领域的应用逐渐深入。为了规范和促进生成式人工智能服务的健康发展,国家互联网信息办公室发布了《生成式人工智能服务已备案信息》。本文将基于已备案信息,分析生成式人工智能服务的发展趋势,并…...

spring功能汇总

1.创建一个dao接口&#xff0c;实现类&#xff1b;service接口&#xff0c;实现类并且service里用new创建对象方式调用dao的方法 2.使用spring分别获取dao和service对象(IOC) 注意 2中的service里面获取dao的对象方式不用new的(DI) 运行测试&#xff1a; 使用1的方式创建servic…...

Transformer - Feed Forward前馈网络

一、数学原理 1. 前馈神经网络公式 2. Dropout公式 二、代码实现 import math import torchimport torch.nn as nnclass FeedForward(nn.Module):def __init__(self, d_model, dff, dropout):super().__init__()self.W1 nn.Linear(d_model, dff)self.W2 nn.Linear(dff, d_mo…...

Compose Multiplatform+Kotlin Multiplatfrom 第五弹跨平台 截图

截图功能 Compose MultiplatformKotlin Multiplatfrom下实现桌面端的截图功能&#xff0c;起码搞了两星期&#xff0c;最后终于做出来了&#xff0c;操作都很流畅&#xff0c;截取的文件大小也正常&#xff0c;可参考支持讨论&#xff01; 功能效果 代码实现 //在jvmMain下创…...

算法题(119):高精度减法

审题&#xff1a; 本题高精度减法主要是要区分正负号&#xff0c;然后进行模拟 思路&#xff1a; 方法一&#xff1a;模拟法 首先本题需要我们利用字符串进行大数相减 第一步&#xff1a;区分s1和s2谁更大 先从数的位数进行判断&#xff0c;然后再从高到低的位数进行判断 第二步…...

使用成员函数指针数组简化C++类中的操作

使用成员函数指针数组简化C类中的操作 在C编程中&#xff0c;我们常常会遇到需要对一组相似的操作进行处理的情况。例如&#xff0c;在一个游戏引擎中&#xff0c;你可能希望角色能够执行一系列的动作&#xff0c;如行走、跳跃或攻击等。为了简化这些操作的管理和调用&#xf…...

WebGL数学手记:矩阵基础

一、矩阵的定义 矩阵&#xff0c;数学术语。在数学中&#xff0c;矩阵&#xff08;Matrix&#xff09;是一个按照长方阵列排列的复数或实数集合。 1.英文发音&#xff08;Matrix&#xff09; Matrix的发音类似于中文的[美吹克斯]&#xff0c;知道它的发音。方便后期看教程时…...

Python爬取数据(二)

一.example2包下的 1.re模块的compile函数使用 import repatternre.compile(r\d) print(pattern) 2.match的方法使用 import re patternre.compile(r\d) # m1pattern.match(one123twothree345four) #参数2&#xff1a;指定起始位置(包含),参数3&#xff1a;终止位置(包含),…...

我的NISP二级之路-01

目录 一.SSE-CMM系统安全工程-能力成熟度模型(Systems Security Engineering - Capability Maturity Model) 二.ISMS 即信息安全管理体系(Information Security Management System),是一种基于风险管理的、系统化的管理体系 三.Kerberos协议 1. 用户登录与 AS 请求 2…...

自制简易 Shell:像搭建积木小屋一样打造命令交互小天地

目录 准备工作&#xff1a;搭建小屋的材料 打造小屋的 “身份牌” 接收指令&#xff1a;小屋的 “对讲机” 拆解指令&#xff1a;把大任务拆成小积木 执行指令&#xff1a;小屋的 “行动队” 特殊指令&#xff1a;小屋的 “特色功能” 小屋的日常运转 完整代码 啥是 …...

WEB安全--内网渗透--利用Net-NTLMv2 Hash

一、前言 在前两篇文章中分析了NTLM协议中Net-NTLMv2 Hash的生成、如何捕获Net-NTLMv2 Hash&#xff0c;现在就来探讨一下在内网环境中&#xff0c;如何利用Net-NTLMv2 Hash进行渗透。 二、Net-NTLM Hash的破解 工具&#xff1a;hashcat 原理&#xff1a;利用其内部的字典对…...

MySQL 数据库操作指南:从数据库创建到数据操作

关键词&#xff1a;MySQL&#xff1b;数据库操作&#xff1b;DDL&#xff1b;DML 一、引言 MySQL 作为广泛应用的关系型数据库管理系统&#xff0c;对于开发人员和数据库管理员而言&#xff0c;熟练掌握其操作至关重要。本文章通过一系列 SQL 示例&#xff0c;详细阐述 MySQL…...

从传递函数到PID控制器

在过程控制中&#xff0c;按偏差的比例&#xff08;P&#xff0c;Proportional&#xff09;、积分&#xff08;I&#xff0c;Integral&#xff09;和微分&#xff08;D&#xff0c;Differential&#xff09;进行控制的PID控制器&#xff08;亦称PID调节器&#xff09;是应用最为…...

抓wifi无线空口包之Ubuntu抓包(二)

一、设置网卡信道和频段&#xff0c;并抓包 1、使用iwconfig查看自己机器的无线网卡名称 wangwang-ThinkCentre-M930t-N000:~$ iwconfig lo no wireless extensions. eno1 no wireless extensions. enxc8a3624ab329 no wireless extensions. wlx90de80d1b5b1 IE…...

使用protobuf编译提示无法打开包括文件: ‘absl/log/absl_log.h’: No such file or directory

问题原因 Protobuf 依赖 Abseil&#xff1a; Protobuf 3.20 版本开始依赖 Abseil&#xff0c;但你的系统未正确安装或配置 Abseil。 头文件路径未包含&#xff1a; 编译器找不到 absl/log/absl_log.h&#xff0c;可能是因为 Abseil 未正确安装或未在项目中设置包含路径。 …...

深入浅出Java 锁 | 源码剖析 | 万字解析

目录 硬件内存结构&Java内存模型 硬件内存结构 Java内存模型&#xff08;JMM&#xff09; JMM中三大特性&#xff1a;原子性、有序性、可见性 Java中有哪些锁&#xff1f; Java中锁可以分成悲观锁和乐观锁的实现。 乐观锁和悲观锁的区别&#xff0c;乐观锁一定好嘛&…...

java流程控制12:流程控制练习

流程控制练习 打印三角型 package com.zheng.struct;public class TestDemo {public static void main(String[] args) {//打印三角形 5行for(int i1;i<5;i){for(int j5;j>i;j--){System.out.print(" ");}for(int j1;j<i;j){System.out.print("*&quo…...

JAVA:ByteBuddy 动态字节码操作库的技术指南

1、简述 ByteBuddy 是一个功能强大的 Java 字节码操作库&#xff0c;可以帮助开发者在运行时动态生成和修改类&#xff0c;而无需直接接触复杂的 ASM API。它被广泛应用于框架开发、AOP&#xff08;面向切面编程&#xff09;、代理类生成、性能监控等领域。 2、ByteBuddy 的优…...