2269. 找到一个数字的 K 美丽值

题目

一个整数 num 的 美丽值定义为 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 。

代码实现思路

一看到寻找子字符串,且定长为k。立马思路延续上一题思路leetcode-1456. 定长子串中元音的最大数目

核心思路:整体单次遍历,滑动窗口左边出,右边进,通过StringBuilder 进行字符拼接并计算。

这一过程符合定长滑动数组的基本思路:入、更新(操作)、出。时间复杂度O(n)

实现代码如下:

public static int divisorSubstrings(int num, int k) {
        char[] cs = String.valueOf(num).toCharArray();
        int length = cs.length;
        if (k > length){
            return 0;
        }
        StringBuilder sb = new StringBuilder();
        int x = 0;
        int count = 0;
        while (x < k) {
            sb.append(cs[x]);
            x++;
        }
        for (int i = k-1; i < length ; i++) {
            int currNum = Integer.parseInt(sb.toString());
            if (currNum != 0 && num % currNum == 0) {
                count++;
            }
            sb.deleteCharAt(0);
            if (i+1 ==length ) break;
            sb.append(cs[i+1]);
        }
        return count;
    }

总结

这种定长滑动数组的基本思路已经可以确定为:入、更新(操作)、出

再遇到类似的也应该换汤不换药了,我觉得这种题的难点是在于如何界定边界值,例如入窗和出窗的下标计算,不过这个可以通过数学规律找出。