算法:按字典顺序在给定索引处查找给定字符串的字谜
Posted
技术标签:
【中文标题】算法:按字典顺序在给定索引处查找给定字符串的字谜【英文标题】:Algo: Find anagram of given string at a given index in lexicographically sorted order 【发布时间】:2017-11-12 07:41:35 【问题描述】:需要编写一个算法以按字典顺序在给定索引处查找给定字符串的 Anagram。例如:
考虑一个字符串:ABC,那么所有字谜都按排序顺序排列:ABC ACB BAC BCA CAB CBA。因此,对于 索引 5 的值是:CAB。此外,考虑 重复 的情况,例如 AADFS anagram 将是索引 32 处的 DFASA
为此,我编写了 Algo,但我认为应该有比这更简单的东西。
import java.util.*;
public class Anagram
static class Word
Character c;
int count;
Word(Character c, int count)
this.c = c;
this.count = count;
public static void main(String[] args)
System.out.println(findAnagram("aadfs", 32));
private static String findAnagram(String word, int index)
// starting with 0 that's y.
index--;
char[] array = word.toCharArray();
List<Character> chars = new ArrayList<>();
for (int i = 0; i < array.length; i++)
chars.add(array[i]);
// Sort List
Collections.sort(chars);
// To maintain duplicates
List<Word> words = new ArrayList<>();
Character temp = chars.get(0);
int count = 1;
int total = chars.size();
for (int i = 1; i < chars.size(); i++)
if (temp == chars.get(i))
count++;
else
words.add(new Word(temp, count));
count = 1;
temp = chars.get(i);
words.add(new Word(temp, count));
String anagram = "";
while (index > 0)
Word selectedWord = null;
// find best index
int value = 0;
for (int i = 0; i < words.size(); i++)
int com = combination(words, i, total);
if (index < value + com)
index -= value;
if (words.get(i).count == 1)
selectedWord = words.remove(i);
else
words.get(i).count--;
selectedWord = words.get(i);
break;
value += com;
anagram += selectedWord.c;
total--;
// put remaining in series
for (int i = 0; i < words.size(); i++)
for (int j = 0; j < words.get(i).count; j++)
anagram += words.get(i).c;
return anagram;
private static int combination(List<Word> words, int index, int total)
int value = permutation(total - 1);
for (int i = 0; i < words.size(); i++)
if (i == index)
int v = words.get(i).count - 1;
if (v > 0)
value /= permutation(v);
else
value /= permutation(words.get(i).count);
return value;
private static int permutation(int i)
if (i == 1)
return 1;
return i * permutation(i - 1);
谁能帮我解决不太复杂的逻辑。
【问题讨论】:
好问题。没有想太多,你的代码对我来说看起来并不过分复杂。 我遇到了同样的问题。这是editorial 的链接。希望这会有所帮助。 使用带有“排列”和“排名”的搜索功能。 【参考方案1】:我编写以下代码来解决您的问题。
我假设给定的字符串是排序的。
permutations(String prefix, char[] word, ArrayList permutations_list) 函数生成给定字符串的所有可能排列而不重复,并将它们存储在名为 permutations_list。因此,单词:permutations_list.get(index -1) 是所需的输出。
例如,假设有人给了我们“aab”这个词。 我们必须递归地解决这个问题:
问题 1:排列(“”,“aab”)。
这意味着我们必须解决问题:
问题 2:排列(“a”,“ab”)。 字符串“ab”只有两个字母,因此可能的排列是“ab”和“ba”。因此,我们将单词“aab”和“aba”存储在 permutations_list 中。
问题 2 已解决。现在我们回到问题 1。 我们交换第一个“a”和第二个“a”,我们意识到这些字母是相同的。所以我们跳过这种情况(我们避免重复)。 接下来,我们交换第一个“a”和“b”。现在,问题 1 发生了变化,我们要解决新的问题:
问题 3:排列(“”,“baa”)。
下一步是解决以下问题:
问题 4:排列(“b”,“aa”)。 字符串“aa”只有两个相同的字母,因此有一个可能的排列“aa”。因此,我们在 permutations_list 中存储单词“baa”
问题 4 已解决。最后,我们回到问题 3,问题 3 已经解决了。最终的 permutations_list 包含“aab”、“aba”和“baa”。
因此,findAnagram("aab", 2) 返回单词“aba”。
import java.util.ArrayList;
import java.util.Arrays;
public class AnagramProblem
public static void main(String args[])
System.out.println(findAnagram("aadfs",32));
public static String findAnagram(String word, int index)
ArrayList<String> permutations_list = new ArrayList<String>();
permutations("",word.toCharArray(), permutations_list);
return permutations_list.get(index - 1);
public static void permutations(String prefix, char[] word, ArrayList<String> permutations_list)
boolean duplicate = false;
if (word.length==2 && word[0]!=word[1])
String permutation1 = prefix + String.valueOf(word[0]) + String.valueOf(word[1]);
permutations_list.add(permutation1);
String permutation2 = prefix + String.valueOf(word[1]) + String.valueOf(word[0]);
permutations_list.add(permutation2);
return;
else if (word.length==2 && word[0]==word[1])
String permutation = prefix + String.valueOf(word[0]) + String.valueOf(word[1]);
permutations_list.add(permutation);
return;
for (int i=0; i < word.length; i++)
if (!duplicate)
permutations(prefix + word[0], new String(word).substring(1,word.length).toCharArray(), permutations_list);
if (i < word.length - 1)
char temp = word[0];
word[0] = word[i+1];
word[i+1] = temp;
if (i < word.length - 1 && word[0]==word[i+1]) duplicate = true;
else duplicate = false;
【讨论】:
【参考方案2】:如果您考虑按字母顺序生成字谜,我认为您的问题会变得简单得多,因此您不必事后对它们进行排序。
以下代码(来自Generating all permutations of a given string)生成字符串的所有排列。这些排列的顺序由输入字符串的初始顺序给出。如果您事先对字符串进行排序,则字谜将因此按排序顺序添加。
为了防止重复,您可以简单地维护一组您已经添加的字符串。如果此 Set 不包含您要添加的字谜,那么您可以安全地将其添加到字谜列表中。
这是我描述的解决方案的代码。我希望您发现它比您的解决方案更简单。
public class Anagrams
private List<String> sortedAnagrams;
private Set<String> handledStrings;
public static void main(String args[])
Anagrams anagrams = new Anagrams();
List<String> list = anagrams.permutations(sort("AASDF"));
System.out.println(list.get(31));
public List<String> permutations(String str)
handledStrings = new HashSet<String>();
sortedAnagrams = new ArrayList<String>();
permutation("", str);
return sortedAnagrams;
private void permutation(String prefix, String str)
int n = str.length();
if (n == 0)
if(! handledStrings.contains(prefix))
//System.out.println(prefix);
sortedAnagrams.add(prefix);
handledStrings.add(prefix);
else
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i + 1, n));
public static String sort(String str)
char[] arr = str.toCharArray();
Arrays.sort(arr);
return new String(arr);
【讨论】:
【参考方案3】:如果您创建一个“下一个排列”方法将数组更改为其下一个字典排列,那么您的基本逻辑可能是在循环中调用该方法n-1
次。
可以在here 找到一个很好的代码描述。这是从该页面改编而来的基本伪代码和 Java 示例。
/*
1. Find largest index i such that array[i − 1] < array[i].
(If no such i exists, then this is already the last permutation.)
2. Find largest index j such that j ≥ i and array[j] > array[i − 1].
3. Swap array[j] and array[i − 1].
4. Reverse the suffix starting at array[i].
*/
boolean nextPermutation(char[] array)
int i = array.length - 1;
while (i > 0 && array[i - 1] >= array[i]) i--;
if (i <= 0) return false;
int j = array.length - 1;
while (array[j] <= array[i - 1]) j--;
char temp = array[i - 1];
array[i - 1] = array[j];
array[j] = temp;
j = array.length - 1;
while (i < j)
temp = array[i];
array[i] = array[j];
array[j] = temp;
i++;
j--;
return true;
【讨论】:
以上是关于算法:按字典顺序在给定索引处查找给定字符串的字谜的主要内容,如果未能解决你的问题,请参考以下文章