问题
I'm learning to solve algorithms
A string comprlsed of digits from 0 to 9 contains a perfect substring If all the elements within a substring occur exactly k times. Calculate the number of perfect substring in s.
Example
Example
s = 1102021222
k = 2
The 6 perfect substrings are:
1. s[0:1] = 11
2. s[0:5] = 110202
3. s[1:6] = 102021
4. s[2:5] = 0202
5. s[7:8] = 22
6. s[8:9] = 22
I'm trying to undertsand this problem and solve it. But not able to undertsand properly. I thought it to calulcate every unique number should be available in string for k
times.
But example says something different.
Can anyone suggest please how to solve this with any example ? I'm kinda of stuck..
回答1:
- Create a
List<String> listSubstrs
of all the substrings of the given string. - In order to check if a substring in
listSubstrs
is a perfect substring, you can define a function in which- Create a frequency
Map
of each letter of the substring. - Iterate the values of the map and return
false
if any of the value is not equal tok
. Returntrue
otherwise.
- Create a frequency
Demo:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
String s = "1102021222";
List<String> listSubstrs = new ArrayList<>();
for (int i = 0; i < s.length(); i++) {
for (int j = i + 1; j <= s.length(); j++) {
listSubstrs.add(s.substring(i, j));
}
}
List<String> perfectSubstrs = listSubstrs.stream()
.filter(str -> isPerfectSubstr(str, 2))
.collect(Collectors.toList());
System.out.println(perfectSubstrs);
}
static boolean isPerfectSubstr(String str, int k) {
Map<Character, Integer> letterFrequencyMap = new HashMap<>();
for (char ch : str.toCharArray()) {
letterFrequencyMap.merge(ch, 1, Integer::sum);
}
for (Integer i : letterFrequencyMap.values()) {
if (i != k) {
return false;
}
}
return true;
}
}
Output:
[11, 110202, 102021, 0202, 22, 22]
回答2:
I said in the comment that there is a quadratic solution. I was wrong - a correct solution is linear. A simple sliding window suffices.
Grow a window to the right, counting digits, until one of the counters reaches exceeds k
. If all the counters are k
or zero, we found the perfect substring. If not, shrink the window from the left, again adjusting counters, until the leading counter decrements. Rinse and repeat.
In pseudocode,
left = 0
right = 0
perfect_counters = 0
zero_counters = ndigits
while left < n:
if right < n:
# Grow the window
digit = array[right]
counter[digit] += 1
if counter[digit] == k:
perfect_counters += 1
if counter[digit] == 1:
zero_counters -= 1
right += 1
if zero_counters + perfect_counters == k:
# This is a perfect substring
print left, right
# Overshoot. Shrink the window.
the_digit = digit
while counter[the_digit] > k:
digit = array[left]
counter[digit] -= 1
if counter[digit] == 0:
zero_counters += 1
left += 1
# It is possible that the resulting string _is_ perfect.
if zero_counters + perfect_counters == k:
print left, right
Of course there is a plenty of room for optimization.
来源:https://stackoverflow.com/questions/65439238/check-if-its-a-perfect-string