简体   繁体   English

字符串中最少重复的字符

[英]Least repeating chararcter in a string

I'm trying to find the least repeating character in a string ,it works for some input but it fails for some input. 我正在尝试查找字符串中重复最少的字符,它对某些输入有效,但对某些输入却失败。

Map<Character, Integer> map = new HashMap<Character, Integer> ();

    String s = "abcdabcdabcdacd";
    char[] chars = s.toCharArray();

    for (Character ch: chars) {
        if (map.containsKey(ch)) {
            map.put(ch, map.get(ch) + 1);
        } else {
            map.put(ch, 1);
        }
    }

    Set<Character> keys = map.keySet();

    for (Character ch: keys) {
        if (map.get(ch) ==1) {
            System.out.println(ch + " ");
        }
    }

I expect the output to be b but it doesn't show anything. 我希望输出为b,但不会显示任何内容。 If i give aabaa as the input then it shows b and that's correct. 如果我给aabaa作为输入,那么它将显示b,这是正确的。

As I commented already, you only check for characters which only occur once, not for the least occurrence. 正如我已经评论过的,您只检查只出现一次的字符,而不是最少出现的字符。

You can change your code by this: 您可以通过以下方式更改代码:

public class PrintB {

    public static void main(String[] args) {
        Map<Character, Integer> map = new HashMap<>();

        String s = "abcdabcdabcdacd";
        char[] chars = s.toCharArray();

        for (Character ch: chars) {
            if (map.containsKey(ch)) {
                map.put(ch, map.get(ch) + 1);
            } else {
                map.put(ch, 1);
            }
        }

        Set<Character> keys = map.keySet();
        boolean broken = false;
        for ( int i = 0; i < s.length(); i++ ) { // the max will be s.length()

            for (Character ch : keys) {
                if (map.get(ch) == i) { // this amount is checked for each char
                    System.out.println(ch + " ");
                    broken = true;
                }
            }
            if ( broken ) {
                i = s.length(); // sure, there are other ways to break out of the loop
            }
        }
    }
}

Using streams you may simply do: 使用流,您可以简单地执行以下操作:

final String s = "abcdabcdabcdacd";

String leastRepeated = 
   s.chars().mapToObj(i -> Character.toString((char) i))      // map to Stream<String>   
    .collect(Collectors.toMap(k -> k, v -> 1, Integer::sum))  // Map<String, Integer>
    .entrySet().stream()                                      // stream over map
    .min(Comparator.comparing(Entry::getValue))               // comparing values in map
    .get().getKey();                                          // get resp entry   

which outputs: 输出:

b b

The reason your code doesn't work the way you would want it to is because your last code block is only printing if the character is being repeated once and only once: 您的代码无法按您希望的方式工作的原因是,您的最后一个代码块仅在字符重复一次且仅重复一次时才打印:

for (Character ch: keys) {
    if (map.get(ch) ==1) {
        System.out.println(ch + " ");
    }

However by using the Collections.min method we can find the lowest map value which we can then use to find the character it belongs to from map keys. 但是,通过使用Collections.min方法,我们可以找到最低的地图值,然后可以使用它从地图键中查找它所属的字符。 Here is the complete code with context: 这是带有上下文的完整代码:

/**
 * @return an array of Character objects that have occured the
 * least amount of times in the given {@code String} parameter.
 * <i>Note that all whitespaces found within the {@code String} will be ignored </i>
 */
public static Character[] getLeastRepeatingCharacters(String text) {

    Map<Character, Integer> map = new HashMap<Character, Integer> ();
    /*
     * Remove all whitespaces from the text as we don't
     * want to include them in our comparison oprations
     */
    text = text.replaceAll("\\s+","");

    for (Character ch : text.toCharArray()) {
        if (map.containsKey(ch)) {
            map.put(ch, map.get(ch) + 1);
        }
        else if (ch != '\0') {
            map.put(ch, 1);
        }
    }
    /*
     * Get map value that occurs the least amount of times
     */
    int leastOccuranceValue = Collections.min(map.values());
    java.util.List<Character> leastOccurances = new java.util.ArrayList<>();
    /*
     * Iterate through the map, find all characters that have
     * occured the least amount of times and add them to a list
     */
    for (java.util.Map.Entry<Character, Integer> entry : map.entrySet()) {
        if (entry.getValue().equals(leastOccuranceValue)) {
            leastOccurances.add(entry.getKey());
        }
    }
    return leastOccurances.toArray(new Character[0]);
}

public static void main(String[] args) {

    String text = "abcdabcdabcdacd";
    Character[] leastRepeating = getLeastRepeatingCharacters(text);

    String log = "Array of charactes that repeated the least amount of times in text '%s':%n%s";
    System.out.printf(log, text, Arrays.toString(leastRepeating));
}

Output: 输出:

Your string sample: 您的字符串示例:

Array of charactes that repeated the least amount of times in text 'abcdabcdabcdacd ':
[b]

String sample provided by Stultuske: Stultuske提供的字符串样本:

Array of charactes that repeated the least amount of times in text 'kambcxdabcdalbcdacd ':
[x, k, l, m]

You have to read the whole map to get the min occurrence, so you can't print in the loop, you should instead collect chars with min occurence, and then print them. 您必须阅读整个地图才能获得最小出现次数,因此您无法在循环中进行打印,而应收集具有最小出现次数的字符,然后进行打印。

    public static void main(String[] args) {
        Map<Character, Integer> map = new HashMap<>();

        String s = "abcdaybcdabcdacdz";
        char[] chars = s.toCharArray();

        for (Character ch: chars) {
            if (map.containsKey(ch)) {
                map.put(ch, map.get(ch) + 1);
            } else {
                map.put(ch, 1);
            }
        }

        List<Character> reps = new ArrayList<>();

        Integer count = chars.length;
        Set<Entry<Character, Integer>> entries = map.entrySet();
        for (Entry<Character, Integer> entry : entries) {
            Integer n = entry.getValue();
            Character c = entry.getKey();
            if(n==count) {
                reps.add(c);
            }else if (n<count) {
                reps = new ArrayList<>();
                reps.add(c);
                count = n;
            }
        }

        for (Character character : reps) {
            System.out.println(character);
        }

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM