【一看就会一写就废 指间算法】找到一个数字的 K 美丽值—— 滑动窗口、字符串

28 阅读2分钟

指尖划过的轨迹,藏着最细腻的答案~

题目:

一个整数 numk 美丽值定义为 num 中符合以下条件的 子字符串 数目:

  • 子字符串长度为 k
  • 子字符串能整除 num

给你整数 numk ,请你返回 numk 美丽值。

注意:

  • 允许有 前缀 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 。

提示:

1num1091 \leq num \leq 10^9
1knum.length1 \leq k \leq num.length (将 num 视为字符串)

分析:

本地需要从num中每次获取k个值作为被除数,k是一个固定值,因此本题可以使用定长滑动窗口:进入窗口——更新答案——离开窗口

具体的我们可以将num使用to_string(num)转换为字符串,然后遍历这个字符串,获取窗口大小k作为被除数,在更新答案时需要注意0不能作为被除数。

AC代码:

class Solution {
public:
    int divisorSubstrings(int num, int k) {
        int ans = 0;
        string numS = to_string(num);
        int n = numS.size();

        string subNumS = "";

        for (int i = 0; i < n; i++) {
            // 进入窗口
            subNumS += numS[i];

            int left = i - k + 1;
            if (left < 0) {
                continue;
            }

            // 更新答案
            int subNum = stoi(subNumS);
            if (subNum != 0 && num % subNum == 0) {
                ans++;
            }

            // 离开窗口
            subNumS = subNumS.substr(1);
        }

        return ans;
    }
};