Find the K-Beauty of a Number
EasyPrompt
The k-beauty of an integer num is defined as the number of substrings of num when it is read as a string that meet the following conditions:
- It has a length of
k. - It is a divisor of
num.
Given integers num and k, return the k-beauty of num.
Note:
- Leading zeros are allowed.
0is not a divisor of any value.
A substring is a contiguous sequence of characters in a string.
Example 1:
Input: num = 240, k = 2
Output: 2
Explanation: The following are the substrings of num of length k:
- "24" from "240": 24 is a divisor of 240.
- "40" from "240": 40 is a divisor of 240.
Therefore, the k-beauty is 2.Example 2:
Input: num = 430043, k = 2
Output: 2
Explanation: The following are the substrings of num of length k:
- "43" from "430043": 43 is a divisor of 430043.
- "30" from "430043": 30 is not a divisor of 430043.
- "00" from "430043": 0 is not a divisor of 430043.
- "04" from "430043": 4 is not a divisor of 430043.
- "43" from "430043": 43 is a divisor of 430043.
Therefore, the k-beauty is 2.
Constraints:
1 <= num <= 1091 <= k <= num.length(takingnumas a string)
Approaches
2 approaches with complexity analysis and trade-offs.
This is the most straightforward approach. It converts the number to a string and then iterates through all possible starting positions to extract substrings of length k. Each substring is then converted back to an integer to check for the divisibility condition.
Algorithm
- Convert the input integer
numto its string representation,s. - Initialize a counter,
kBeautyCount, to zero. - Loop through the string
sfrom the first character up to the character at indexs.length() - k. Let the loop variable bei. - Inside the loop, extract the substring of length
kstarting at indexiusings.substring(i, i + k). - Convert this substring into an integer, let's call it
subNumber. - Check if
subNumberis not zero. - If
subNumberis not zero, perform a modulo operation:num % subNumber. If the result is 0, it meanssubNumberis a divisor ofnum. - If
subNumberis a non-zero divisor, incrementkBeautyCount. - After the loop finishes, return
kBeautyCount.
Walkthrough
The algorithm works by first converting the number num into a string s to easily access its digits. It then iterates from the beginning of the string to the last possible starting point for a substring of length k. In each iteration, it extracts the k-length substring, converts it to an integer, and checks if this integer is a non-zero divisor of the original number num. A counter is maintained to keep track of how many such substrings are found, which is the final k-beauty value.
class Solution { public int divisorSubstrings(int num, int k) { String s = Integer.toString(num); int n = s.length(); int count = 0; if (k > n) { return 0; } for (int i = 0; i <= n - k; i++) { // Extract substring of length k String subStr = s.substring(i, i + k); // Convert substring to integer int subNum = Integer.parseInt(subStr); // Check for k-beauty conditions if (subNum != 0 && num % subNum == 0) { count++; } } return count; }}Complexity
Time
O(D * k), where `D` is the number of digits in `num`. The loop runs `D - k + 1` times. In each iteration, `substring()` takes `O(k)` time (in modern Java versions) and `Integer.parseInt()` also takes `O(k)` time. This results in a total complexity of `O((D-k) * k)`, which simplifies to `O(D * k)`.
Space
O(D). This is required to store the string representation of `num`, where `D` is the number of digits. Additionally, each call to `substring()` creates a new string of length `k`, contributing `O(k)` temporary space within the loop.
Trade-offs
Pros
Very simple and intuitive to write and understand.
Directly translates the problem statement into code.
Cons
Less efficient due to repeated creation and parsing of substrings. For each step of the iteration, it re-parses
k-1digits that were already part of the previous substring.
This approach improves upon the naive method by avoiding repeated parsing of overlapping parts of the number. It first parses the initial k-digit number. Then, it "slides" a window of k digits across the string representation of the number one position at a time, updating the integer value of the window using simple arithmetic instead of re-parsing the entire substring.
Algorithm
- Convert the input integer
numto its string representation,s. - Initialize a counter,
kBeautyCount, to zero. - Calculate the value of the first
k-digit substring and store it inwindowValue. - Check if this initial
windowValuemeets the k-beauty conditions and update the count if it does. - Pre-calculate
powerOf10 = 10^(k-1). This will be used to efficiently update the window's value. - Loop from
i = ktos.length() - 1. This loop slides the window to the right. - In each iteration, update
windowValuearithmetically to reflect the new window:- Use the modulo operator to remove the most significant digit:
windowValue = windowValue % powerOf10. - Shift the remaining digits to the left:
windowValue = windowValue * 10. - Add the value of the new rightmost digit:
windowValue = windowValue + (s.charAt(i) - '0').
- Use the modulo operator to remove the most significant digit:
- Check if the updated
windowValuemeets the k-beauty conditions and increment the count accordingly. - After the loop, return
kBeautyCount.
Walkthrough
This optimized method still begins by converting the number to a string. However, instead of repeatedly calling substring and parseInt, it calculates the integer value of the first k-digit window once. Then, it iterates through the rest of the string, and for each step, it updates the window's integer value in constant time. This is done by arithmetically removing the value of the digit that's leaving the window and adding the value of the new digit that's entering. This avoids the O(k) cost of re-parsing at each step, leading to a more efficient overall solution.
class Solution { public int divisorSubstrings(int num, int k) { String s = Integer.toString(num); int n = s.length(); int count = 0; if (k > n) { return 0; } long windowValue = 0; long powerOf10 = 1; // Calculate initial window value and the power of 10 needed for sliding for (int i = 0; i < k; i++) { windowValue = windowValue * 10 + (s.charAt(i) - '0'); if (i < k - 1) { powerOf10 *= 10; } } // Check the first window if (windowValue != 0 && num % windowValue == 0) { count++; } // Slide the window across the rest of the string for (int i = k; i < n; i++) { // Update window value: remove leading digit's effect, shift, add new digit windowValue = (windowValue % powerOf10) * 10 + (s.charAt(i) - '0'); // Check for k-beauty conditions if (windowValue != 0 && num % windowValue == 0) { count++; } } return count; }}Complexity
Time
O(D), where `D` is the number of digits in `num`. Converting the number to a string takes `O(D)`. The initial window setup takes `O(k)`. The main loop runs `D - k` times, and each iteration involves constant-time arithmetic operations. The total time is `O(D) + O(k) + O(D - k)`, which simplifies to `O(D)`.
Space
O(D). The space is dominated by the storage required for the string representation of `num`, where `D` is the number of digits.
Trade-offs
Pros
More efficient than the naive approach, with a linear time complexity relative to the number of digits.
Avoids expensive repeated substring creation and parsing operations inside the main loop.
Cons
The implementation is slightly more complex than the naive approach.
Still requires converting the number to a string, which uses extra space.
Solutions
Solution
class Solution {public int divisorSubstrings(int num, int k) { int ans = 0; String s = "" + num; for (int i = 0; i < s.length() - k + 1; ++i) { int t = Integer.parseInt(s.substring(i, i + k)); if (t != 0 && num % t == 0) { ++ans; } } return ans; }}class Solution: def divisorSubstrings(self, num: int, k: int) -> int: ans = 0 s = str(num) for i in range(len(s) - k + 1): t = int(s[i: i + k]) if t and num % t == 0: ans += 1 return ansclass Solution {public: int divisorSubstrings(int num, int k) { int ans = 0; string s = to_string(num); for (int i = 0; i < s.size() - k + 1; ++i) { int t = stoi(s.substr(i, k)); ans += t && num % t == 0; } return ans; }};Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.