需要编写Algo,以按字典顺序排序的给定索引查找给定字符串的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);
}
}
有人可以用不那么复杂的逻辑来帮助我。
答案 0 :(得分:1)
我编写以下代码来解决您的问题。
我假设给定的String已排序。
排列(String prefix,char [] word,ArrayList permutations_list) 函数生成给定字符串的所有可能排列而不重复,并将它们存储在名为<的列表中强> permutations_list 即可。因此,单词: permutations_list.get(index -1)是所需的输出。
例如,假设某人给了我们“#34; aab&#34;”这个词。 我们必须递归地解决这个问题:
问题1:排列(&#34;&#34;,&#34; aab&#34;)。
这意味着我们必须解决问题:
问题2:排列(&#34; a&#34;,&#34; ab&#34;)。 字符串&#34; ab&#34;只有两个字母,因此可能的排列是&#34; ab&#34;和&#34; ba&#34;。因此,我们在permutations_list中存储单词&#34; aab&#34;和&#34; aba&#34;。
问题2已经解决。现在我们回到问题1。 我们交换第一个&#34; a&#34;第二个&#34; a&#34;我们意识到这些字母是一样的。所以我们跳过这种情况(我们避免重复)。 接下来,我们交换第一个&#34; a&#34;和&#34; b&#34;。现在,问题1已经改变,我们想要解决新的问题:
问题3:排列(&#34;&#34;,&#34; baa&#34;)。
下一步是解决以下问题:
问题4:排列(&#34; b&#34;,&#34; aa&#34;)。 字符串&#34; aa&#34;只有两个相同的字母,因此有一种可能的排列&#34; aa&#34;。因此,我们在permutations_list中存储单词&#34; baa&#34;
问题4已经解决。最后,我们回到问题3,问题3已经解决了。最终的permutations_list包含&#34; aab&#34;,&#34; aba&#34;和&#34; baa&#34;。
因此,findAnagram(&#34; aab&#34;,2)返回单词&#34; aba&#34;。
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;
}
}
}
答案 1 :(得分:0)
如果你考虑按字母顺序生成字谜,我认为你的问题会变得简单得多,所以你不必在事后对它们进行排序。
以下代码(来自Generating all permutations of a given string)生成String的所有排列。这些排列的顺序由输入String的初始顺序给出。如果事先对String进行排序,那么将按排序顺序添加字谜。
为防止重复,您只需维护一组已添加的字符串即可。如果此Set不包含您要添加的anagram,则可以安全地将其添加到字谜列表中。
以下是我所描述的解决方案的代码。我希望你发现它比你的解决方案更简单。
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);
}
}
答案 2 :(得分:0)
如果你创建一个&#34;下一个排列&#34;将数组更改为下一个词典排列的方法,然后你的基本逻辑可能只是在循环中调用该方法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;
}