Check if its a perfect string [closed]

时光毁灭记忆、已成空白 提交于 2020-12-27 05:31:19

问题


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:


  1. Create a List<String> listSubstrs of all the substrings of the given string.
  2. 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 to k. Return true otherwise.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!