哈希集包含的字符位置准确,但字符位置不正确



我有一个类,它确定2个字符数组中有多少匹配字符。使用HashSetcontains方法,如果一个字符数组包含第二个数组中的Character,则显示该字符
问题是,如果两个匹配的字符出现在多个位置。

例如,如果array 1 = adcdarray 2 = a05ddd,则d出现3次,而不是2次。
如何修改此项以获得正确的字符数?代码在应该生成"add"时生成"addd"对于不正确的字符,结果将是"a--dd"

HashSet<Character> hash = new HashSet<Character>();        
String word1 = "adcd";
String word2 = "a05ddd";
char[] ch1 = word1.toCharArray();
char[] ch2 = word2.toCharArray();
Character character = null;
String charLocation = "";
int count = 0;
for (int i = 0; i < ch1.length; i++) 
{
hash.add(ch1[i]); 

}
for (int i = 0; i < ch2.length; i++) 
{
character = ch2[i]; 
if (hash.contains(character)) 
{
charLocation = charLocation + character;
count++;
} 
if (!hashSet.contains(character)) 
correctCharPlacements = correctCharPlacements + "-";
}

很可能需要收集有关字符频率的数据,因此应该用映射替换set。然后,可以根据常见字符这两个单词中字符的最小频率来构建结果字符串:

// helper method to build frequency map for a word/string
private static Map<Character, Integer> freqMap(String word) {
return word.chars()
.mapToObj(c -> (char)c)
.collect(Collectors.toMap(x -> x, x -> 1, Integer::sum, LinkedHashMap::new));
}
static String common(String w1, String w2) {
if (null == w1 || null == w2) {
return null;
}
Map<Character, Integer> map1 = freqMap(w1);
Map<Character, Integer> map2 = freqMap(w2);
Set<Character> commonChars = new LinkedHashSet<>(map1.keySet());
commonChars.retainAll(map2.keySet());
return commonChars.stream()
.map(x -> String.valueOf(x).repeat(Math.min(map1.get(x), map2.get(x))))
.collect(Collectors.joining(""));
}

测试:

System.out.println("common = " + common("adcd", "a05ddd"));

输出:

common = add

更新

由于String::repeat从Java 11开始就可用,因此可以使用String::join+Collections.nCopies:将其替换为Java 8兼容代码

static String common(String w1, String w2) {
if (null == w1 || null == w2) {
return null;
}
Map<Character, Integer> map1 = freqMap(w1);
Map<Character, Integer> map2 = freqMap(w2);
Set<Character> commonChars = new LinkedHashSet<>(map1.keySet());
commonChars.retainAll(map2.keySet());

return commonChars.stream()
.map(x -> String.join("", Collections.nCopies(Math.min(map1.get(x), map2.get(x)), String.valueOf(x))))
.collect(Collectors.joining(""));
}

在线演示:

System.out.println("Java version: " + System.getProperty("java.version"));
System.out.println("common = " + common("adcd", "a05ddd"));

输出:

Java version: 1.8.0_201
common = add

更新2

为了保持结果中第二个字符串中字符的顺序,并用'-'替换缺失的字符,可以实现以下方法:

static String common2(String w1, String w2) {
if (null == w1 || null == w2) {
return null;
}
Map<Character, Integer> map1 = freqMap(w1);
StringBuilder sb = new StringBuilder();
for (char c : w2.toCharArray()) {
if (map1.containsKey(c) && map1.get(c) > 0) {
sb.append(c);
map1.merge(c, -1, Integer::sum); // decrement the character counter in the first map
} else if (!map1.containsKey(c)) { // character missing in the first word
sb.append('-');
}
}
return sb.toString();
}

测试

String[][] tests = {
{"adcd", "ad05dd"},
{"adcd", "d05add"},
{"adcd", "d05dadd"},
};
for (String[] test : tests) {
System.out.printf("common(%s, %s) = %s%n", test[0], test[1], common(test[0], test[1]));
}

输出:

common(adcd, ad05dd) = ad--d
common(adcd, d05add) = d--ad
common(adcd, d05dadd) = d--da

最新更新