我试图找到给定6个字母的所有3、4、5和6个字母单词。我通过将6个字母的每个组合与ArrayList单词的比较来找到它们。我已经在代码方面做了很多工作,以达到这一点。

我测试了检查六个字母单词并得到720个,因为6 * 5 * 4 * 3 * 2 * 1 = 720,表示我没有两次检查任何单词。我无法通过消除重复检查来加快速度,因为我已经摆脱了所有检查。

我还能提高速度吗?

请注意,sortedDictionary仅包含大约200个单词。

for(int l1 = 0; l1 < 6; l1++){
    for(int l2 = 0; l2 < 6; l2++){
        if(l2 != l1)
            for(int l3 = 0; l3 < 6; l3++){
                if(l3 != l1 && l3 != l2){
                    if(sortedDictionary.contains(""+anagramCharacters[l1]+anagramCharacters[l2]+anagramCharacters[l3]))
                        anagram_words.add(""+anagramCharacters[l1]+anagramCharacters[l2]+anagramCharacters[l3]);
                    for(int l4 = 0; l4 < 6; l4++){
                        if(l4 != l1 && l4 != l2 && l4 != l3){
                            if(sortedDictionary.contains(""+anagramCharacters[l1]+anagramCharacters[l2]+anagramCharacters[l3]+anagramCharacters[l4]))
                                anagram_words.add(""+anagramCharacters[l1]+anagramCharacters[l2]+anagramCharacters[l3]+anagramCharacters[l4]);
                            for(int l5 = 0; l5 < 6; l5++){
                                if(l5 != l1 && l5 != l2 && l5 != l3 && l5 != l4){
                                   if(sortedDictionary.contains(""+anagramCharacters[l1]+anagramCharacters[l2]+anagramCharacters[l3]+anagramCharacters[l4]+anagramCharacters[l5]))
                                       anagram_words.add(""+anagramCharacters[l1]+anagramCharacters[l2]+anagramCharacters[l3]+anagramCharacters[l4]+anagramCharacters[l5]);
                                   for(int l6 = 0; l6 < 6; l6++){
                                       if(l6 != l1 && l6 != l2 && l6 != l3 && l6 != l4 && l6 != l5)
                                           if(sortedDictionary.contains(""+anagramCharacters[l1]+anagramCharacters[l2]+anagramCharacters[l3]+anagramCharacters[l4]+anagramCharacters[l5]+anagramCharacters[l6]))
                                               anagram_words.add(""+anagramCharacters[l1]+anagramCharacters[l2]+anagramCharacters[l3]+anagramCharacters[l4]+anagramCharacters[l5]+anagramCharacters[l6]);
                                    }   
                                }
                            }   
                        }
                    }
                }
            }
    }
}

我的解决方案仍然可能不是最佳的编写代码,但是它将加载时间从大约1-2秒减少到几乎即时(没有明显的等待时间;没有)。 t实际上测试了多长时间)。

for(int i = 0; i < sortedDictionary.size(); i++){
    for(int index = 0; index < anagram.length(); index++)
        anagramCharacters[index] = anagram.charAt(index);
    forloop:
    for(int i2 = 0; i2 < sortedDictionary.get(i).length(); i2++){
        for(int i3 = 0; i3 < anagramCharacters.length; i3++){
            if(sortedDictionary.get(i).charAt(i2) == anagramCharacters[i3]){
                anagramCharacters[i3] = 0;
                break;
            }
            else if(i3 == anagramCharacters.length-1)
                break forloop;
        }
        if(i2 == sortedDictionary.get(i).length()-1)
            anagram_words.add(sortedDictionary.get(i));
    }
}


评论

只是为了确保:您不能在一个单词中两次使用相同的字母?除非这6个字母中的某些字母本身是重复的?

您需要加快的唯一“速度”是理解代码所花费的时间。认真地,将其拆分为子例程将通过帮助您了解代码的实际作用来加快代码的速度。

#1 楼

如果字典中的单词数量很少,那么您最好将代码翻过来,遍历字典中的单词,并检查其中的单词是否包含6个字母

多次将字符串保留在char数组中会更有效

char[] prefix= new char[6];
for(int l1 = 0; l1 < 6; l1++){
    prefix[0]=anagramCharacters[l1];
    for(int l2 = 0; l2 < 6; l2++)
        if(l2 != l1){
        prefix[1]=anagramCharacters[l2];


然后您可以使用新的String(prefix,0,3)创建字符串(将3替换为长度)

否则递归进行救援:

List<String> createAnagrams(char[] chars, SortedSet<String> sortedDictionary){
    List<String result = new ArrayList<String>();
    fillListWithAnagrams(result, sortedDictionary, chars, 0);
    return result;
}

void fillListWithAnagrams(List<String> result, SortedSet<String> sortedDictionary, char[] chars, int charIndex){
    if(charIndex>=3){
       String resultString = new String(chars,0,charIndex);
       if(sortedDictionary.contains(resultString);
           list.add(resultString);
    }

    if(charIndex>=chars.length)
       return;//end of the line

    for(int i = charIndex;i<chars.length;i++){
        char t = chars[i];
        chars[i] = chars[charIndex];
        chars[charIndex] = t;

        fillListWithAnagrams(list, sortedDictionary, chars, charIndex+1);

        // revert the char array for the next step
        //t=chars[charIndex];
        chars[charIndex] = chars[i];
        chars[i] = t;
    }

}




#2 楼

在开始之前,我必须说:谢谢您的光临。 Java For Loops的混乱几乎被轻描淡写了。现在,让我们开始工作吧?

在下面的答案中,我假设sortedDictionaryanagram_words均为List<String>类型。我还假设anagramCharacters的类型为char[]。 >
这样的代码重复了多次:它在做,主要是为了让您能够了解它有什么更好的选择。
if(sortedDictionary.contains(""+anagramCharacters[l1]+anagramCharacters[l2]+anagramCharacters[l3]))
     anagram_words.add(""+anagramCharacters[l1]+anagramCharacters[l2]+anagramCharacters[l3]);


我们只需调用一个方法:

private void addWord(char... chars) {
    String string = "";
    for (char ch : chars) string += ch; // Create a strings of the chars
    if (sortedDictionary.contains(string))
        anagram_words.add(string);
}


带有索引的变量

只要您发现自己使用变量名包含编号的值,例如addWord()l1l2l3,STOP并认为“数组在这里有用吗?”。创建l4远比使用多个变量int[] lettersl1l2灵活得多。如果所有l3-变量都位于l数组内,则目前可以简化一些事情:



此:

if (sortedDictionary.contains(....)) anagram_words.add(...)


将成为

addWord(anagramCharacters[l1], anagramCharacters[l2], anagramCharacters[l3]);


/>
此:

if(l4 != l1 && l4 != l2 && l4 != l3)


可以成为方法

if(letters[3] != letters[0] && letters[3] != letters[1] && letters[3] != letters[2])



我们之前对letters所做的调用只需要包含要检查的索引数,而不是每个字符。

if(letters[3] != letters[0] && letters[3] != letters[1] && letters[3] != letters[2])



所以现在完成了,现在还剩下什么?

完成上述重构后,剩下的仍然是:

private boolean lastLetterDifferent(int index) {
    for (int i = 0; i < index; i++) {
        if (letters[i] == letters[index]) return false;
    }
    return true;
}


看起来很干净,但这有多灵活?如果我们要使用8个字母的单词或12个字母的单词怎么办?不,您不应该继续这种模式并添加更多的for循环!那么还有什么其他选择?递归方法,我的朋友!

要做到这一点,我们需要几个辅助方法。您提到了720。恰好720等于6阶乘。因此,让我们创建一个阶乘方法。

private void addWord(int numberOfChars) {
    String string = "";
    for (int i = 0; i < numberOfChars; i++) string += anagramCharacters[letters[i]]; // Create a strings of the chars
    if (sortedDictionary.contains(string))
        anagram_words.add(string);
}


这是递归的,因为它在某些情况下会自行调用。更确切地说,当addWord时。递归方法很有趣,因此让我们创建另一个!

for(letters[0] = 0; letters[0] < 6; letters[0]++){
    for(letters[1] = 0; letters[1] < 6; letters[1]++) {
        if(lastLetterDifferent(1)) {
            for(letters[2] = 0; letters[2] < 6; letters[2]++) {
                if(letters[2] != letters[0] && letters[2] != letters[1]) {
                    addWord(3);
                    for(letters[3] = 0; letters[3] < 6; letters[3]++) {
                        if (lastLetterDifferent(3)) {
                            addWord(4);
                            for(letters[4] = 0; letters[4] < 6; letters[4]++){
                                if (lastLetterDifferent(4)) {
                                    addWord(5);
                                    for(letters[5] = 0; letters[5] < 6; letters[5]++){
                                        if (lastLetterDifferent(5)) {
                                            addWord(6);
                                        }
                                    }   
                                }
                            }   
                        }
                    }
                }
            }
        }
    }
}


每次调用此方法时,它都会根据x >= 2的值在values列表中选择一个索引。然后,它从iteration列表中获取该索引的元素,从values列表中删除该元素,并将其添加到名为values的列表中(这将是方法的结果。然后,此方法调用自身以添加当前元素的所有其余元素迭代。

将其放在一起:

我们将需要另一个实用程序方法来将字符列表转换为字符串(同样,该方法尚未完全优化。在那里有很多更快的方法可以执行此操作。

评论


\ $ \ begingroup \ $
感谢您的详细答复,当我有机会改进我的编码风格时,我会仔细阅读。我通过其他人的建议找到了解决我的问题的方法,但这绝对是最有用的信息。 +1,互联网需要更多像您这样的人:)谢谢!
\ $ \ endgroup \ $
–java
13年11月28日在18:32

\ $ \ begingroup \ $
您实际上应该使用新的String(char [])构造函数,而不是使用循环将字符添加到字符串中。
\ $ \ endgroup \ $
– AJMansfield
13年11月29日在1:39

\ $ \ begingroup \ $
好吧,只需编辑以使用possibe处的String构造函数,否则使用StringBuilder;还向将char列表转换为字符串的方法添加了null检查。
\ $ \ endgroup \ $
– AJMansfield
13年11月29日在1:50

\ $ \ begingroup \ $
@AJMansfield说了什么。 docs.oracle.com/javase/7/docs/api/java/lang/…。除此之外,答案还不错。
\ $ \ endgroup \ $
– Aseem Bansal
13年11月29日在18:39



\ $ \ begingroup \ $
@AseemBansal我知道可以在这里进行改进。我不想提高太多,只专注于最重要的事情。我认为使用String并对其进行迭代添加对于OP更全面。
\ $ \ endgroup \ $
–西蒙·福斯伯格
2013年12月3日21:26

#3 楼

这个问题要求递归。...

private static final void checkWord(char[] chars, char[]current, int len, List<String> results) {
    if (len == chars.length) {
        final String result = new String(current);
        if (sortedDictionary.contains(result)) {
             results.add(result);
        }
    } else {
        // get the next combination for what is left in the chars
        for int (i = xx; i < yy; i++) {
            current[len] = .... // next char to try
            checkWord(chars, current, len+1 results);
        }
    }
}



EDIT

这是一个“不错”的问题,它与所有最喜欢的教育问题,阶乘,组合和置换...

这里是在过程中运行的工作代码...。我在有需要的地方进行了评论。我这样做是为了在这里记录一下情况,并在以后需要时可以参考。:

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;


public class Words {

    /**
     * Calculate all possible ways to permute data sets of up to 'max' values...
     * <p>
     * The result is a multi-dimensional array, with result[2] being the ways to
     * permute 2-sized data sets ([1,2],[2,1]), and result[3] the way to permute 3-sized sets:
     * ([1,2,3],[1,3,2],[2,3,1],[2,1,3],[3,1,2],[3,2,1]),
     * etc.
     * 
     * @param max the largest set to calculate permutations for.
     * @return the possible ways to permute sets of values up to max values in size
     */
    private static final int[][][] permutations(int max) {
        int[][][] ret = new int[max + 1][][];
        ret[0] = new int[0][];
        ret[1] = new int[1][1];
        for (int i = 2; i <= max; i++) {
            ret[i] = new int[factorial(i)][];
            int[] remaining = new int[i];
            for (int j = 0; j < i; j++) {
                remaining[j] = j;
            }
            permutationGen(i, ret[i], 0, new int[0], remaining);
        }
        return ret;
    }

    /**
     * calculate the factorial of a number.
     * The factorial is the number of permutations available for a given set of values.
     * @param n the number to calculate
     * @return the factorial (n!)
     */
    private static int factorial(int n) {
        int ret = n;
        while (--n > 1) {
            ret *= n;
        }
        return ret;
    }

    /**
     * Recursive function to calculate the permutations of a dataset of a specified size.
     * @param size The number of elements to calculate the permutations for
     * @param store The place to store the permutations
     * @param nextstore the next location to save values in the store
     * @param used the positions that have been used in already in building the current permutations
     * @param remaining the remaining positions that need to be used.
     * @return the index of the next permutation to save
     */
    private static int permutationGen(final int size, final int[][] store, int nextstore, final int[] used, final int[] remaining) {

        if (used.length == size) {
            store[nextstore] = used;
            return nextstore + 1;
        }
        int [] nremain = Arrays.copyOfRange(remaining, 1, remaining.length);
        for (int r = 0; r < remaining.length; r++) {
            int [] nused = Arrays.copyOf(used, used.length + 1);
            if (r > 0) {
                nremain[r - 1] = remaining[r - 1];
            }
            nused[used.length] = remaining[r];
            nextstore = permutationGen(size, store, nextstore, nused, nremain);

        }
        return nextstore; 
    }

    /**
     * Recursive combination function. It determines all possible combinations for a set of data, and for
     * each combination it also then runs through all permutations.
     * With the permutations it checks to see whether the word created by that combination/permutation is
     * a real word, and if it is, it adds it to the anagrams solution set.
     * @param words the valid words
     * @param chars the actual characters we can use to anagram
     * @param charpos the position in the chars that we are currently processing
     * @param current the letters we currently have in our combination already.
     * @param currentlen the number of letters in current that are valid.
     * @param permutes the possible permutations for different-sized datasets.
     * @param anagrams where to store the valid words when we find them.
     */
    private static void checkCombinations(final String[] words, final char[] chars, final int charpos,
            final char[] current, final int currentlen, final int[][][] permutes, final Collection<String> anagrams) {

        if (currentlen >= current.length) {
            return;
        }

        for (int i = charpos; i < chars.length; i++) {
            current[currentlen] = chars[i];

            // This is th recursive function to calculate combinations.
            checkCombinations(words, chars, i + 1, current, currentlen + 1, permutes, anagrams);

            // for each combination, run through all the permutations.
            char[] strchr = new char[currentlen + 1];
            for (int[] perm : permutes[currentlen + 1]) {
                for (int j = 0; j <= currentlen; j++) {
                    strchr[j] = current[perm[j]];
                }
                String word = new String(strchr);
                if (Arrays.binarySearch(words, word) >= 0) {
                    anagrams.add(word);
                }
            }

        }

    }

    public static void main(String[] args) throws IOException {
        System.out.println("Reading Linux words file (typically /usr/share/dict/linux.words)");
        String words[] = Files.readAllLines(Paths.get("linux.words"), StandardCharsets.UTF_8).toArray(new String[0]);
        System.out.println("Convert all to lowercase");
        for (int i = 0; i < words.length; i++) {
            words[i] = words[i].toLowerCase();
        }
        System.out.println("Sort all words (" + words.length + ")");
        Arrays.sort(words);
        char[] chars = "abcdef".toLowerCase().toCharArray();

        Set<String> anagrams = new TreeSet<>();

        System.out.println("building permutations for " + chars.length + " sizes");
        int[][][] permutations = permutations(chars.length);

        System.out.println("calculating combinations and permutations of '" + new String(chars) + "'.");
        long time = System.nanoTime();
        checkCombinations(words, chars, 0, new char[chars.length], 0, permutations, anagrams);
        System.out.printf("Found %d words.... in %.3fms\n", anagrams.size(), (System.nanoTime() - time) / 1000000.0);
        for (String s : anagrams) {
            System.out.println(s);
        }

    }

}


#4 楼

嵌套的for循环不是您唯一的问题。即使可以重组代码以避免嵌套,组合爆炸也会给您带来可伸缩性问题。换句话说,您可能需要检查6个事实! =基本问题是每个六个字母的单词有720个字典条目。您需要一种新算法:一种在不产生所有可能性的情况下检查有效性的算法。

我建议您对六个有效字母的列表进行排序。然后检查每个候选单词的排序字母是否是已排序有效字母的子序列。 (子序列就像子字符串,但可能存在间隙。)

public static List<String> findWords(char[] letters, List<String> sortedDictionary) {
    letters = Arrays.copyOf(letters, letters.length);
    Arrays.sort(letters);
    char[] buf = new char[letters.length];

    List<String> anagramWords = new ArrayList<String>();
    for (String word : sortedDictionary) {
        int len = word.length();
        if (len < 3 || len > letters.length) {
            continue;
        }
        word.getChars(0, len, buf, 0);
        Arrays.sort(buf, 0, len);
        if (isSubsequence(buf, len, letters)) {
            anagramWords.add(word);
        }
    }
    return anagramWords;
}

private static boolean isSubsequence(char[] needle, int needleLen, char[] haystack) {
    for (int n = 0, h = 0; n < needleLen && h < haystack.length; n++, h++) {
        while (needle[n] > haystack[h]) {
            h++;
            if (h >= haystack.length) {
                return false;
            }
        }
        if (needle[n] < haystack[h]) {
            return false;
        }
        assert needle[n] == haystack[h];
    }
    return true;
}


#5 楼

一旦意识到要对字符进行置换,就应该在那里停下来并研究出一般的操作方法。

这里是置换迭代的基类:

public abstract class PermutationsIterator implements Iterator<List<Integer>> {
  // Length of the lists required.
  protected final int length;
  // The working list.
  protected final List<Integer> indexes;
  // The next to deliver.
  private List<Integer> next = null;

  public PermutationsIterator(int length) {
    this.length = length;
    indexes = new ArrayList<>(length);
    for (int i = 0; i < length; i++) {
      indexes.add(i);
    }
    // Deliver the base one first.
    this.next = Collections.unmodifiableList(indexes);
  }

  // Return true if a next was available.
  protected abstract boolean getNext();

  @Override
  public boolean hasNext() {
    if (next == null) {
      // Is there one?
      if ( getNext() ) {
          // That's next!
          next = Collections.unmodifiableList(indexes);
      }
    }
    return next != null;
  }

  @Override
  public List<Integer> next() {
    List<Integer> n = hasNext() ? next : null;
    next = null;
    return n;
  }

  @Override
  public void remove() {
    throw new UnsupportedOperationException("Cannot remove from permutations");
  }

}


在这里,您可以实现一个简单的字典式迭代器,如下所示:简单为:

public class LexicographicPermutationsIterator extends PermutationsIterator implements Iterator<List<Integer>> {

  public LexicographicPermutationsIterator(int length) {
    super(length);
  }

  @Override
  protected boolean getNext() {
    boolean got = false;
    // Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
    int k = -1;
    for (int i = 0; i < length - 1; i++) {
      if (indexes.get(i) < indexes.get(i + 1)) {
        k = i;
      }
    }
    if (k >= 0) {
      int ak = indexes.get(k);
      // Find the largest index l such that a[k] < a[l].
      int l = k + 1;
      for (int i = 0; i < length; i++) {
        if (ak < indexes.get(i)) {
          l = i;
        }
      }
      // Swap the value of a[k] with that of a[l].
      Collections.swap(indexes, k, l);
      // Reverse the sequence from a[k + 1] up to and including the final element a[n].
      Collections.reverse(indexes.subList(k + 1, indexes.size()));
      // We got one.
      got = true;
    }
    return got;
  }

}


#6 楼

由于顺序无关紧要,因此您可以查看所有排序的单词。您还可以预构建索引,并确保代码较暖。查看22K个单词的字典,在我的笔记本电脑上平均需要9微秒

这是更快的,因为只有42种组合的字母组合在一起,长度为3到6,每个字母lookup为O(1),因此不需要扫描所有单词。

BTW如果您想提高某些代码的性能,则确实需要计时,因为通常您可能会更改某些假设它会更快,但不是。如果您不衡量性能,那是您的猜测。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;

public class WordsSearchMain {
    public static void main(String... ignored) throws IOException {
        Dictionary dict = new Dictionary("/usr/share/dict/words", 3, 6);
        final String alphabet = "abcdefghifjklmnopqrstuvwxyz";
        String[] words = new String[22];
        for (int i = 0; i < words.length; i++)
            words[i] = alphabet.substring(i, i + 6);

        // warmup the code
        for (int i = 0; i < 12000; i += words.length)
            for (String word : words)
                dict.allWordsFor(word);
        // time to do 20 searches
        Map<String, Set<String>> searches = new LinkedHashMap<>();
        long start = System.nanoTime();
        for (String word : words)
            searches.put(word, dict.allWordsFor(word));
        long time = System.nanoTime() - start;

        System.out.printf("Took an average of %.1f micro-seconds, searching %,d words%n",
                time / words.length / 1e3, dict.count);
        for (Map.Entry<String, Set<String>> entry : searches.entrySet()) {
            System.out.println(entry);
        }
    }

}

class Dictionary {
    private final int min;
    Map<String, List<String>> wordForLetters = new HashMap<>();
    int count = 0;

    public Dictionary(String filename, int min, int max) throws IOException {
        this.min = min;
        try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
            for (String line; (line = br.readLine()) != null; ) {
                if (line.length() >= min && line.length() <= max) {
                    char[] chars = line.toLowerCase().toCharArray();
                    Arrays.sort(chars);
                    String sorted = new String(chars);
                    List<String> words = wordForLetters.get(sorted);
                    if (words == null)
                        wordForLetters.put(sorted, words = new ArrayList<>());
                    words.add(line);
                    count++;
                }
            }
        }
    }

    public Set<String> allWordsFor(String s) {
        Set<String> allWords = new TreeSet<>();
        String lower = s.toLowerCase();
        for (int i = (1 << min) - 1; i < (1 << s.length()); i++) {
            int bitCount = Integer.bitCount(i);
            if (bitCount < min) continue;
            StringBuilder sb = new StringBuilder(bitCount);
            for (int j = 0; j < s.length(); j++)
                if (((i >> j) & 1) != 0)
                    sb.append(lower.charAt(j));
            final List<String> words = wordForLetters.get(sb.toString());
            if (words != null)
                allWords.addAll(words);
        }
        return allWords;
    }
}


印刷品

Took an average of 9.1 micro-seconds, searching 22,299 words
abcdef=[Abe, Dec, Feb, Fed, abed, ace, aced, bad, bade, bead, bed, cab, cad, dab, deaf, deb, decaf, face, faced, fad, fade, fed]
bcdefg=[Dec, Feb, Fed, bed, beg, deb, fed]
cdefgh=[Che, Dec, Fed, chef, fed]
defghi=[Fed, Gide, die, dig, fed, fie, fig, hid, hide, hie, hied]
efghif=[fie, fig, hie]
fghifj=[fig, jig]
ghifjk=[JFK, jig]
hifjkl=[JFK, ilk]
ifjklm=[JFK, Jim, Kim, ilk, mil, milk]
fjklmn=[JFK]
jklmno=[Jon, Lon, Mon, Monk, monk]
klmnop=[Lon, Mon, Monk, Polk, lop, monk, mop, pol]
lmnopq=[Lon, Mon, Qom, lop, mop, pol]
mnopqr=[Mon, Qom, Ron, mop, morn, nor, norm, porn, pro, prom, romp]
nopqrs=[Ron, Son, nor, porn, pro, pros, son, sop]
opqrst=[Post, opt, opts, port, ports, post, pot, pots, pro, pros, rot, rots, sop, sort, sot, sport, spot, stop, strop, top, tops, tor, tors]
pqrstu=[Prut, Stu, pus, put, puts, rust, rut, ruts, spur, spurt, sup, ups]
qrstuv=[Stu, rust, rut, ruts]
rstuvw=[Stu, rust, rut, ruts]
stuvwx=[Stu, tux]
tuvwxy=[tux]
uvwxyz=[]


#7 楼

首先,让我们考虑一下数字。

您需要检查720字谜和2700字。您可以扫描所有单词并查看它们是否包含在您的字母中,而不是生成所有字谜和查找它们。您正在一次循环中进行4次迭代的一次昂贵的查找交易。那可能会更快。

这就是为什么我要注释您的第二个代码片段。我认为这是一个不错的开始。


集合上的循环可以用更紧凑的样式编写。也。为单词声明一个变量避免了多次重新计算sortedDictionary.get(i)。
从字符串中提取字符可以用string.toCharArray()表示。
还可以从循环外部测试是否完成循环。
不必打破命名循环。
通常最好将诸如word.getCharAt(i)之类的表达式保存到局部变量中,而不是一遍又一遍地重新计算它。不过,不确定getCharAt是否有很大的区别。

到目前为止,我们已经拥有了

    for(String word : sortedDictionary){
        char[] anagramCharacters = anagram.toCharArray();
        int i2, i3;
        for(i2 = 0; i2 < word.length(); i2++){
            char wordChar = word.charAt(i2);
            for(i3 = 0; i3 < anagramCharacters.length; i3++){
                if(wordChar == anagramCharacters[i3]){
                    anagramCharacters[i3] = 0;
                    break;
                }
            }
            // break out if wordChar did not match any anagramCharacters
            if(i3 == anagramCharacters.length)
                break;
        }
        // add the word if all letters were found in the anagram letters
        if(i2 == word.length())
            anagram_words.add(word);
    }


,但是我仍然不满意。我更喜欢使用布尔变量来控制程序流。他们以某种方式解释了执行流程的原因。
    for(String word : sortedDictionary){
        char[] anagramCharacters = anagram.toCharArray();
        boolean anagramOK = true;
        for(char wordChar : word.toCharArray()){
            boolean found = false;
            for(int i = 0; !found && i < anagramCharacters.length; i++){
                if(wordChar == anagramCharacters[i]){
                    anagramCharacters[i] = 0;
                    found = true;
                }
            }
            // if not found, the word is not compatible with the anagram letters
            if(!found){
                anagramOK = false;
                break;
            }
        }
        // add the word if all letters were found in the anagram letters
        if(anagramOK)
            anagram_words.add(word);
    }


PS:是的,有些人喜欢在每条语句两边加上括号。