华为 OD 训练营 · 题解精讲
LC2269. 找到一个数字的K美丽值
题目描述
一个整数 num 的 k 美丽值定义为 num 中符合以下条件的 子字符串 数目: 子字符串长度为 k 。 子字符串能整除 num 。 给你整数 num 和 k ,请你返回 num 的 k 美丽值。 注意: 允许有 前缀 0 。 0 不能整除任何值。 一个 子字符串 是一个字符串里的连续一段字符序列。
示例 1: 输入:num = 240, k = 2 输出:2 解释:以下是 num 里长度为 k 的子字符串:
- "240" 中的 "24" :24 能整除 240 。
- "240" 中的 "40" :40 能整除 240 。
所以,k 美丽值为 2 。 示例 2: 输入:num = 430043, k = 2 输出:2 解释:以下是 num 里长度为 k 的子字符串:
- "430043" 中的 "43" :43 能整除 430043 。
- "430043" 中的 "30" :30 不能整除 430043 。
- "430043" 中的 "00" :0 不能整除 430043 。
- "430043" 中的 "04" :4 不能整除 430043 。
- "430043" 中的 "43" :43 能整除 430043 。
所以,k 美丽值为 2 。
提示: 1 <= num <= 10^(9) 1 <= k <= num.length (将 num 视为字符串)
题目解析
题目在说什么
这道题其实是在玩一个数字游戏。给你一个数字(比如240),再给你一个长度k(比如2)。你要做的是:把这个数字当成一串字符("240"),然后从里面截取所有长度为k的连续片段(比如"24"和"40")。每个片段也是一个数字,你要检查这个数字能不能整除原来的数字(240)。能整除的片段就算一个“美丽值”。最后统计有多少个这样的片段。
注意两点:
- 如果片段是"00"这种,它等于0,0不能做除数,所以不算。
- 允许片段开头有0,比如"04"就是数字4,但4能不能整除原数,要看计算。
所以本质上就是:把数字转成字符串,滑窗取所有长度为k的子串,转成整数,判断是否能整除原数,计数。
思路是怎么来的
想象你有一串珍珠项链,上面有数字珠子。现在你要检查所有连续的、长度为k的一小段珠子,看它们组成的数字能不能被整条项链代表的数字整除。
这个任务很机械:你只需要从第一个珠子开始,每次往后挪一个位置,取k个珠子,组成数字,做除法判断。这就是“滑动窗口”的思路——一个固定大小的窗口在字符串上滑动,每次取窗口里的内容。
为什么用滑动窗口?因为子串必须是连续的,而且长度固定。最直接的办法就是遍历所有可能的起始位置,从0到len(s)-k,每个位置取k个字符。这样不会漏掉任何一个子串。
另外要注意,取出来的子串可能以0开头,比如"04"。转成整数后就是4,没问题。但如果子串全是0,比如"00",转成整数是0,0不能做除数,所以要跳过。
代码逐步拆解
我们先用一个简单的Python代码来实现。假设num=240,k=2。
class Solution:
def divisorSubstrings(self, num: int, k: int) -> int:
s = str(num) # 把数字转成字符串,比如 "240"
n = len(s) # 字符串长度,这里是3
count = 0 # 计数器,记录美丽值
# 遍历所有可能的起始位置 i,从0到 n-k
for i in range(n - k + 1):
# 取从i开始,长度为k的子串
sub = s[i:i+k] # 比如 i=0时取"24",i=1时取"40"
val = int(sub) # 转成整数,比如24, 40
# 如果val不等于0,并且num能被val整除
if val != 0 and num % val == 0:
count += 1 # 美丽值加1
return count关键步骤解释:
1. s = str(num):把数字变成字符串,这样才能方便地取子串。比如240变成"240"。
2. n = len(s):知道字符串长度,方便控制循环范围。
3. for i in range(n - k + 1):这个循环控制起始位置。为什么是n-k+1?因为最后一个子串的起始位置是n-k。比如"240"长度3,k=2,起始位置可以是0和1(3-2+1=2个位置)。