刚刚完成了最近的作业,但我知道它可能更有效率。它从命令行读取两个单词,忽略空格和标点符号,并确定它们是否是字谜。我的内容如下;据我所知,它完全正常运作。
/**
* Find out if a string is an anagram of another string
*
*/
import java.util.Arrays;
public class Anagram
{
public static void main(String[] args)
{
if (args.length != 2)
System.out.println("You did not enter two words!");
else
printWords(args[0], args[1]);
}
// method to determine whether two strings have the same chars
public static boolean areAnagrams(String wordOne, String wordTwo)
{
// new strings for letters only
String ltrsOnlyOne = lettersOnly(wordOne);
String ltrsOnlyTwo = lettersOnly(wordTwo);
// convert strings to lowercase char arrays
char[] first = ltrsOnlyOne.toLowerCase().toCharArray();
char[] second = ltrsOnlyTwo.toLowerCase().toCharArray();
// sort char arrays using sort method
Arrays.sort(first);
Arrays.sort(second);
if (Arrays.equals(first, second))
return true;
else
return false;
}
public static String lettersOnly(String word)
{
int length = word.length();
StringBuilder end = new StringBuilder(length);
char x;
for (int i = (length - 1); i >= 0; i--) {
x = word.charAt(i);
if (Character.isLetter(x)) {
end.append(x);
}
}
return end.toString();
}
public static void printWords(String wordOne, String wordTwo)
{
boolean b = areAnagrams(wordOne, wordTwo);
if (b == true) {
System.out.println(wordOne + " is an anagram of "+ wordTwo);
}
if (b == false) {
System.out.println(wordOne + " is not an anagram of "+ wordTwo);
}
}
}
答案 0 :(得分:12)
lettersOnly
的返回值丢失您的lettersOnly
方法不会修改其参数,它会返回新的字符串。当你调用它时,你需要用这个返回值做一些事情。否则你只是在调用它并丢弃结果。
// method to determine whether two strings have the same chars
public static boolean sameChars(String wordOne, String wordTwo)
{
lettersOnly(wordOne);
lettersOnly(wordTwo);
wordOne = lettersOnly(wordOne);
wordTwo = lettersOnly(wordTwo);
...
}
在main()
中,您无需检查其返回值即可调用sameChars
。由于sameChars
不会修改其参数或有任何其他副作用,因此该调用是死代码,应该删除。
public static void main(String[] args)
{
if (args.length != 2) {
System.out.println("You did not enter two words!");
}
sameChars(args[0], args[1]);
printWords(args[0], args[1]);
}
if
语句虽然您的if
语句是正确的,但使用==
与true
和false
进行比较并非惯用语。使用布尔值时,无需进行显式比较。它更短,读取更好,简单地省略比较。
if (sameChars(wordOne, wordTwo) == true) {
if (sameChars(wordOne, wordTwo)) {
System.out.println(wordOne + " is an anagram of "+ wordTwo);
}
if (sameChars(wordOne, wordTwo) == false) {
if (!sameChars(wordOne, wordTwo)) {
System.out.println(wordOne + " is not an anagram of "+ wordTwo);
}
请注意== false
如何被等效的!
(NOT)替换。
实际上,没有理由重复拨打sameChars
。拥有看起来如此相似的代码应该在你的脑海中引起一个小小的警报。 “应该有办法消除重复的代码,”你想。是的,我们将第二个if
切换为else
!
if (sameChars(wordOne, wordTwo)) {
System.out.println(wordOne + " is an anagram of "+ wordTwo);
}
else {
System.out.println(wordOne + " is not an anagram of "+ wordTwo);
}
沿着类似的方向,您可以简化以下语句集:
if (Arrays.equals(first, second))
return true;
else
return false;
当equals()
的结果为真时,返回true。否则当它为假时你返回false。如果你考虑一下,你实际上只是返回equals
返回的内容。您实际上可以完全消除if
和else
,只是直接返回equals
的结果。咦!
return Arrays.equals(first, second);
这种变化比前一次更加先进。如果您以前从未见过这种变化,您可能会发现这种变化有点奇怪。但它确实相当于四行版本。
通常,当程序员编写for
个循环时,它们从0开始并迭代到某个上限。您是否有理由将循环编写为降序循环?
for (int i = (length - 1); i >= 0; i--) {
x = word.charAt(i);
if (Character.isLetter(x)) {
end.append(x);
}
}
有些程序员会像这样向后循环,这是一种“更有效”的可疑尝试。如同,它们只执行一次计算(length - 1)
,所以它稍快一些。我个人认为这浪费时间和脑力。
事实上,向后写你的lettersOnly
函数有一个奇怪的副作用,在删除不需要的字符后,以相反的顺序返回字符串。事实证明这并不重要,因为您稍后将字符按字母顺序排序。但这是一种可以在以后咬你的东西。事情就是这样,你因为排序而逃脱了逆转。我会将循环切换为正常的0到n顺序迭代:
for (int i = 0; i < length; ++i) {
x = word.charAt(i);
if (Character.isLetter(x)) {
end.append(x);
}
}
答案 1 :(得分:3)
执行时间:
如果要改善执行时间,可以计算每个单词中每个字母出现的次数,然后比较计数。这样,您可以避免排序(具有O(n * log n)
复杂度)并在线性(O(n)
)时间内解决问题。
Javadoc:一个小问题,类(/** ... */
)的javadoc注释应该在类声明(public class ...
)之前出现。现在你在javadoc注释和类声明之间有一个import语句。
答案 2 :(得分:1)
我会将santize步骤lettersOnly()
移动到sameChars()
之外的单独方法,从main调用。它效率不高,但代码更清晰:
public static void main(String[] args)
{
if (args.length != 2) {
System.out.println("You did not enter two words!");
}
String wordOne = lettersOnly(args[0]);
String wordTwo = lettersOnly(args[1]);
printWords(wordOne, wordTwo);
}
// method to determine whether two strings have the same chars
public static boolean sameChars(String wordOne, String wordTwo)
{
// convert strings to lowercase char arrays
char[] first = wordOne.toLowerCase().toCharArray();
char[] second = wordTwo.toLowerCase().toCharArray();
Arrays.sort(first);
Arrays.sort(second);
return Arrays.equals(first, second);
}
public static void printWords(String wordOne, String wordTwo)
{
boolean isAnagram = sameChars(wordOne, wordTwo);
if (isAnagram)
{
System.out.println(wordOne + " is an anagram of "+ wordTwo);
}
else
{
System.out.println(wordOne + " is not an anagram of "+ wordTwo);
}
}
答案 3 :(得分:0)
您只需拨打一次sameChars
即可。否则,在false的情况下,您将小写并迭代两次数组。尝试:
public static void printWords(String wordOne, String wordTwo)
{
boolean same = sameChars(wordOne, wordTwo);
if (same) {
System.out.println(wordOne + " is an anagram of "+ wordTwo);
} else {
System.out.println(wordOne + " is not an anagram of "+ wordTwo);
}
}
答案 4 :(得分:0)
在剥离非字母时,为什么要把结果填回字符串呢,当你要做的就是将它们再次放入数组中时?
char[] first = word1.toCharArray();
int numLettersFirst = 0;
for(char l: first)
if(Character.isLetter(l))
first[numLettersFirst++] = Character.toLower(l);
如果两个字符串的字母数不同,则它们不是字谜。否则排序并比较它们 - 但要小心只包括数组的第一个numLetters。
答案 5 :(得分:0)
我今天制作了这个代码,不使用数组来检查一个单词是否是另一个单词的字谜...对我有效...希望它可以帮助你。
import java.util.Scanner;
public class Anagrams
{
//method for if lengths are different
public static boolean length (String word, String check)
{
if (word.length() !=check.length())
{
return false;
}
return true;
}
// display information
public static void main (String[]args)
{
Scanner input = new Scanner (System.in);
//prompt user to enter two words and assign one to String "word" and the other to String "check"
System.out.println("Please enter a word:");
String word = input.nextLine();
System. out. println("Please enter another word to check if it is an anagram of the first:");
String check = input.nextLine();
int add = 0;//keeps track of number of letters that are correct to eachother
//first check if length is correct
if (length(word,check) == false)
{
System.out.println("There is no anagram present.");
}
else if (length(word,check)== true) //if length is correct, continue checking for anagram
{
// check if each letter is in both words
for (int i=0;i<word.length();i++) //for loop through each letter in word
{
for (int x=0;x<check.length();x++) //for loop through each letter in check
{
if (word.charAt(i)==check.charAt(x)) //if letter in first word is the same as one in the next
{
add++;
break;// break out of loop section if the letter is found more than once
}
}
}
if (add == word.length())//if the number of matching letters equals the number of letters in
//the word entered by the user, display that the words are anagrams of eachother
{
System. out.println (check + " is an anagram of " + word);
}
}
}