我在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
?
答案 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;
}
在这里演示: