“在字符串中查找第一个非重复字符”,了解HashTable与HashMap以确保插入顺序?

时间:2017-08-30 01:54:42

标签: java

我在Firecode.io上遇到了这个问题,其中:

firstNonRepeatedCharacter( "abcdcd" ) --> 'a'
firstNonRepeatedCharacter( "cbcd" ) --> 'b'
firstNonRepeatedCharacter( "cdcd" ) --> null

我想出的解决方案是:

public static Character firstNonRepeatedCharacter(String str) {
    if (str == null) return null;

    Hashtable<Character, Integer> map = new Hashtable<Character, Integer>();

    for (int i = 0; i < str.length(); i++) {
        char c = str.charAt(i);
        if (map.containsKey(c)) {
            map.put(c, map.get(c) + 1);
        } else {
            map.put(c, 1);
        }

    }

    for (Character key : map.keySet()) {
        if (map.get(key) == 1) return key;
    }

    return null;
}

第一个测试案例失败了,得到了:

firstNonRepeatedCharacter( "abcdcd" ) --> 'b'  // 'a' is correct

我意识到我正在假设插入顺序,所以我尝试了HashMap

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

最终通过所有案件。

根据我所阅读的内容,HashMap应经常用于Hashtable,但HashMap甚至不能保证支持顺序,LinkedHashMap也可以。它是否正确?我对测试用例感到很幸运,应该使用LinkedHashMap

1 个答案:

答案 0 :(得分:0)

正如您所建议的,使用LinkedHashMap在这里会非常有用,因为它会跟踪插入到地图中的键值对的插入顺序。所以你需要做的就是只记录你看过每封信多少次。插入字符时,增加计数器,除非之前从未见过,在这种情况下,您指定的值为1。然后,按照插入顺序向下走列表,并返回仅出现一次的第一个字符。这是一个有效的实施方案:

public static Character firstNonRepeatedCharacter(String str) {
    if (str == null) return null;

    // use a LinkedHashMap, which maintains insertion order
    // keep a counter of how many times a character is observed, which defaults to 1
    // for characters never seen before
    LinkedHashMap<Character, Integer> map = new LinkedHashMap<>();
    for (int i = 0; i < str.length(); i++) {
        Integer cnt = map.get(str.charAt(i));
        map.put(str.charAt(i), cnt == null ? 1 : cnt.intValue() + 1);
    }

    // now just walk the list, in insertion order, and return the first key
    // whose value is 1 (indicating that it never got repeated)
    for (Map.Entry<Character, Integer> entry : map.entrySet()) {
        if (entry.getValue() == 1) {
            return entry.getKey();
        }
    }

    // return null if no such key appearing only once occurred in the string
    return null;
}

在这里演示:

Rextester