代码之家  ›  专栏  ›  技术社区  ›  flash

检查字符串的所有字符是否包含相同的次数

  •  1
  • flash  · 技术社区  · 6 年前

    我正在研究以下问题陈述:

    如果字符串的所有字符都相同,则该字符串有效 字符串中的1个索引,其余字符将出现在 相同的次数。给定一个字符串s,确定它是否有效。如果 所以,返回YES,否则返回NO。

    s=abc ,它是有效字符串,因为频率 {a:1,b:1,c:1} s=abcc 因为我们可以去掉一个 c 和 在剩下的字符串中每个字符有一个。如果 s=abccc 但是,字符串无效,因为我们只能删除 c . 那会留下 {a:1,b:1,c:2} .

    我想出了下面的代码,但它没有按预期的工作,这是失败的输入 abcdefghhgfedecba . 它正在打印“否”,但对于该输入应该是“是”。

    private static String isValid(String s) {
        if (s == null || s.equals("")) {
            return "NO";
        }
        Map<Character, Integer> frequencies = new HashMap<>();
        for (char ch : s.toLowerCase().toCharArray())
            frequencies.put(ch, frequencies.getOrDefault(ch, 0) + 1);
    
        int count = 0;
        // Iterating over values only
        for (Integer value : frequencies.values()) {
            if (value == 2) {
                count++;
            }
        }
        if (count >= 1) {
            return "YES";
        }
        return "NO";
    }
    

    我在这里干什么?做这件事最有效的方法是什么?

    3 回复  |  直到 6 年前
        1
  •  2
  •   Mureinik    6 年前

    计算频率是正确的想法,尽管我不知道为什么你要检查地图上的值是否正确 2 . 一旦我计算了这些频率,我会创建一个具有每个频率的字符数的反向映射,然后:

    1. 如果映射的大小为1,则表示所有字符的频率相同-字符串有效。
    2. 在任何其他情况下,字符串都将无效。


    private static boolean isValid(String s) {
        TreeMap<Long, Long> frequencyCounts =
                s.chars()
                 .boxed()
                 // Frequency map
                 .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
                 .values()
                 .stream()
                 // Frequency of frequencies map
                 .collect(Collectors.groupingBy
                                     (Function.identity(),
                                      TreeMap::new,
                                      Collectors.counting()));
    
        if (frequencyCounts.size() == 1) {
            return true;
        }
    
        if (frequencyCounts.size() == 2) {
            Iterator<Map.Entry<Long, Long>> iter = frequencyCounts.entrySet().iterator();
            Map.Entry<Long, Long> minEntry = iter.next();
            long minFrequency = minEntry.getKey();
            long numMinFrequency = minEntry.getValue();
    
            if (minFrequency == 1L && numMinFrequency == 1L) {
                return true;
            }
    
            Map.Entry<Long, Long> maxEntry = iter.next();
            long maxFrequency = maxEntry.getKey();
            long numMaxFrequency = maxEntry.getValue();
            if (numMaxFrequency == 1L && maxFrequency == minFrequency + 1L) {
                return true;
            }
        }
    
        return false;
    }
    


    为了回答评论中的问题,频率映射和“频率频率”映射也可以用Java 7的语法构造,尽管它可能没有那么优雅:

    Map<Character, Long> frequencies = new HashMap<>();
    for (int i = 0; i < s.length(); ++i) {
        char c = s.charAt(i);
        if (frequencies.containsKey(c)) {
            frequencies.put(c, frequencies.get(c) + 1L);
        } else {
            frequencies.put(c, 1L);
        }
    }
    
    TreeMap<Long, Long> frequencyCounts = new TreeMap<>();
    for (Long freq : frequencies.values()) {
        if (frequencyCounts.containsKey(freq)) {
            frequencyCounts.put(freq, frequencyCounts.get(freq) + 1L);
        } else {
            frequencyCounts.put(freq, 1L);
        }
    }
    
        2
  •  0
  •   Nawnit Sen    6 年前

    下面的代码工作正常。我在这里要做的是存储数组中每个字符的频率,然后将其转换为列表,因为我们需要稍后的时间点。接下来,我将list转换为set,并从中删除了零,因为在对应于输入字符串中不存在的字符的list中存在零。若set在去掉零后只有on元素,则表示所有元素都有相同的频率 返回true . 如果集合有两个以上的元素,则意味着无法通过在一个位置删除一个字符来使其成为有效字符串 . 如果集合有两个值,我们从集合中取最小值和最大值。如果有一个字符有一个频率,我们可以使它有效,这就是第一个if条件。第二个条件是,如果b/w max和min的差是一,max只有一个频率,那么我们可以从max中删除一个字符并使其有效。

    static String isValid(String s) {
    
            Integer arr[] = new Integer[26];
            Arrays.fill(arr, 0);
            //fill the frequency of every character in array arr
            for (int i = 0; i < s.length(); i++) {
                arr[s.charAt(i) - 97]++;
            }
            //convert array to list of integer     
            List<Integer> arrList = Arrays.asList(arr);
    
            //convert list to set and remove zero bcos zero correspond to char that is not present
            HashSet<Integer> set = new HashSet<Integer>(arrList);
            set.remove(new Integer(0));
            int len = set.size();
            // if size==1 means all freq are same
            if (len == 1)
                return "YES";
            else if (len == 2) {
                List<Integer> list = new ArrayList<>(set);
                int x = list.get(0);
                int y = list.get(1);
                int max = (x > y) ? x : y;
                int min = (x < y) ? x : y;
    
                 // if min elemnnt has value one and freuency one
                if (Collections.frequency(arrList, min) == 1 && min == 1) {
                    return "YES";
                }
              //if max-min==1 and there are only one elemnt with value=max      
             else if (max - min == 1) {
                    if ((Collections.frequency(arrList, max) == 1)) {
                        return "YES";
                    } else {
                        return "NO";
                    }
                } 
              // if no of element is more than
              else {
                    return "NO";
                }
    
            } else
                return "NO";
        }
    
        3
  •  0
  •   Tanmay jain    6 年前

    爪哇8

    import java.util.*;
    public class MyClass {
        public static void main(String args[]) {
            Scanner scan = new Scanner(System.in);
            System.out.println(isValid(scan.next()));
    
        }
    
        private static String isValid(String s) {
            if (s == null || s.equals("")) {
              return "NO";
            }
    
            // frequencies ( hashmap) character : frequency 
            // contains frequency of each character of given string input
            Map<Character, Integer> frequencies = new HashMap<>();
            for (char ch : s.toLowerCase().toCharArray())
              frequencies.put(ch, frequencies.getOrDefault(ch, 0) + 1);
    

    ........................................................................................................................................................

            // freqTypesCount ( hashmap) 
            // frequency_type : number_of_chars_having this frequency_type 
            Map<Integer, Integer> freqTypesCount = new HashMap<>();
            for (int ch : frequencies.values())
              freqTypesCount.put(ch, freqTypesCount.getOrDefault(ch, 0) + 1);
    
    
            if( freqTypesCount.size() == 1){
                // it means all the chars of string occurs same number of time
                return "YES";
            }
            else if( freqTypesCount.size() > 2){
                // aaabbbbccdd
                // a : 3 b: 4 c:2 d:2 --> {3:1, 4:1, 2:2}
                // we can't make this string a valid string just by deleting single char
                return "NO";
            }
            else{
                int valid_freq = Collections.max(freqTypesCount.entrySet(), Map.Entry.comparingByValue()).getKey(); 
                int deleted = 0;
    
                for (Map.Entry<Character, Integer> entry : frequencies.entrySet())
                { 
                    int thisCharCount = entry.getValue();
    
                    if(thisCharCount != valid_freq){
    
                        if(deleted == 0){
                            if(thisCharCount - 1 == valid_freq || thisCharCount - 1 == 0){
                                deleted += 1;
                            }
                            else{
                                return "NO";
                            }
                        }
                        else{
                             return "NO";
                        }
                    }
                }
    
                return "YES" ;
            }
        }
    }
    

    .....................................................................................................................................................................

    蟒蛇3

    from collections import Counter
    
    inp_string = input()
    
    def isValidStr( string):
        char_counter_dict = Counter( string)
        count_type_counter_dict = Counter(char_counter_dict.values())
    
        if len(count_type_counter_dict) == 1:
            return "YES"
        elif len(count_type_counter_dict) > 2:
            return "NO"
        else:
            valid_freq = count_type_counter_dict.most_common()[0][0]
    
            deleted = 0
    
            for char,count in char_counter_dict.items():
    
                if count != valid_freq:
    
                    if deleted == 0:
                        if count - 1 == valid_freq or count - 1 == 0:
                            deleted += 1
    
                        else:
                            return "NO"
    
                    else:
                        return "NO"
    
    
            return "YES"
    
    print(isValidStr(inp_string))