使用基本 Java 检查两个字符串是否互为变位字符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36180897/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Checking if two Strings are anagram of each other using basic Java
提问by Prakhar Londhe
I am writing following code in java Netbeans which is working quite good for normal anagrams. But if the two text fields contain words which contain repetitive letters, then the code fail to work. What may be the problem and how can I solve it? I am quite basic to Java and cannot understand Arrays yet.
我正在用 java Netbeans 编写以下代码,这对于普通字谜来说非常好。但是,如果两个文本字段包含包含重复字母的单词,则代码将无法工作。可能是什么问题,我该如何解决?我对 Java 很基础,还不能理解数组。
String s1= t1.getText();
String s2= t2.getText();
int b=0,c=0;
if(s1.length()!=s2.length())
System.out.print("No");
else {
for(int i=0;i<s1.length();i++) {
char s = s1.charAt(i);
for(int j=0;j<s2.length();j++) {
if(s==s2.charAt(j)){
b++;
}
}
if(b==0)
break;
}
if(b==0)
System.out.print("No");
else
System.out.print("YES");
}
System.out.print(b);
采纳答案by Ivan Valeriani
I would go for something simpler to reason about: two strings are anagrams if, once sorted, they match exactly. So in Java it would be something like:
我会去寻找一些更简单的推理:如果两个字符串在排序后完全匹配,则它们是字谜。所以在Java中它会是这样的:
String s1 = "cat";
String s2 = "tac";
boolean isAnagram = false;
if (s1.length() == s2.length()) {
char[] s1AsChar = s1.toCharArray();
char[] s2AsChar = s2.toCharArray();
Arrays.sort(s1AsChar);
Arrays.sort(s2AsChar);
isAnagram = Arrays.equals(s1AsChar, s2AsChar);
}
回答by Bohemian
You want to compare the sorted characters. It's a one-liner:
您想比较排序后的字符。这是一个单行:
return Arrays.equals(s1.chars().sorted().toArray(),
s2.chars().sorted().toArray());
Arrays.equals()
compares lengths and all elements for you.
Arrays.equals()
为您比较长度和所有元素。
回答by SomeJavaGuy
Since you seem to be a beginner, heres a solution that doesn′t involve functions from other classes or streams. It does only involve the usage of arrays and the fact that a char
can also represent an int
.
由于您似乎是初学者,因此这里有一个不涉及其他类或流的函数的解决方案。它只涉及数组的使用以及 achar
也可以表示 an的事实int
。
public static void main(String[] args) throws ParseException {
String s1= "anagram";
String s2= "margana";
// We make use of the fact that a char does also represent an int.
int lettersS1[] = new int[Character.MAX_VALUE];
int lettersS2[] = new int[Character.MAX_VALUE];
if(s1.length()!=s2.length())
System.out.print("No");
else {
// Loop through the String once
for(int i = 0; i<s1.length() ;++i) {
// we can just use the char value as an index
// and increase the value of it. This is our identifier how often
// each letter was aviable in the String. Alse case insensitive right now
lettersS1[s1.toLowerCase().charAt(i)]++;
lettersS2[s2.toLowerCase().charAt(i)]++;
}
// set a flag if the Strings were anagrams
boolean anag = true;
// We stop the loop as soon as we noticed they are not anagrams
for(int i = 0;i<lettersS1.length&&anag;++i) {
if(lettersS1[i] != lettersS2[i]) {
// If the values differ they are not anagrams.
anag = false;
}
}
// Depending on the former loop we know if these two strings are anagrams
if(anag) {
System.out.print("Anagram");
} else {
System.out.print("No anagram");
}
}
}
回答by Long Vu
Here my solution, we count the appearance of each character in the first string then subtracting it from the count in the second string. Finally, check if the character count is not 0 then the two string is not anagram.
在我的解决方案中,我们计算第一个字符串中每个字符的出现次数,然后从第二个字符串中的计数中减去它。最后,检查字符数是否不为 0,则两个字符串不是字谜。
public static boolean isAnagram(String a, String b){
//assume that we are using ASCII
int[] charCnt = new int[256];
for(int i = 0; i < a.length(); i++){
charCnt[a.charAt(i)]++;
}
for(int i = 0; i< b.length(); i++){
charCnt[b.charAt(i)]--;
}
for(int i = 0; i<charCnt.length; i++){
if(charCnt[i] != 0) return false;
}
return true;
}
回答by Alex Salauyou
One more solution, based on occurrence counter:
另一种解决方案,基于发生计数器:
static boolean areAnagrams(CharSequence a, CharSequence b) {
int len = a.length();
if (len != b.length())
return false;
// collect char occurrences in "a"
Map<Character, Integer> occurrences = new HashMap<>(64);
for (int i = 0; i < len; i++)
occurrences.merge(a.charAt(i), 1, Integer::sum);
// for each char in "b", look for matching occurrence
for (int i = 0; i < len; i++) {
char c = b.charAt(i);
int cc = occurrences.getOrDefault(c, 0);
if (cc == 0)
return false;
occurrences.put(c, cc - 1);
}
return true;
}
Though this solution is less elegant than "sort-and-compare", it might be more effective for long strings with a small chances to be anagrams since it operates in O(n)instead of O(n logn)and returns as soon as matching occurrence is not found at some position in a second string.
尽管此解决方案不如“排序和比较”优雅,但对于不太可能成为字谜的长字符串可能更有效,因为它以O(n)而不是O(n logn) 运行并尽快返回在第二个字符串的某个位置找不到匹配的出现。
Stepping out of "Basic Java" territory, I modified the algorithm to handle surrogate pairsas well. Here collected and matched are not char
s, but int
codepoints:
走出“基本 Java”领域,我修改了算法以处理代理对。这里收集和匹配的不是char
s,而是int
代码点:
static boolean areAnagrams(CharSequence a, CharSequence b) {
int len = a.length();
if (len != b.length())
return false;
// collect codepoint occurrences in "a"
Map<Integer, Integer> ocr = new HashMap<>(64);
a.codePoints().forEach(c -> ocr.merge(c, 1, Integer::sum));
// for each codepoint in "b", look for matching occurrence
for (int i = 0, c = 0; i < len; i += Character.charCount(c)) {
int cc = ocr.getOrDefault((c = Character.codePointAt(b, i)), 0);
if (cc == 0)
return false;
ocr.put(c, cc - 1);
}
return true;
}