查找单词中所有非重复字母的排列

时间:2018-06-23 21:51:34

标签: java algorithm recursion

给出3个唯一字母:您可以使用递归功能打印六个可能的字母的非重复组合。 “ cat”应输出:cat,act,atc,tac,tca和cta。这是我的程序,找不到递归算法。这是我的尝试:

 static void findWords(StringBuilder string, int start, int stride) {
    //1. iterate through all possible combinations of the chars recursively

    System.out.println(string);

    if (stride < string.length() && start < string.length())
    {
        char temp = string.charAt(stride);
        string.setCharAt(stride, string.charAt(start));
        string.setCharAt(start, temp);

        findWords(string, start, stride + 1);

        findWords(string, start + 1, stride + 1 );


    }
}

public static void main(String[] args)
{

   StringBuilder word = new StringBuilder("cat");
   findWords(word,0,1);
}

3 个答案:

答案 0 :(得分:1)

解决方案:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {

    static List<String> resultList = new ArrayList<>();

    static void computeResult(char[] s, int pos, String resultString) {
        if (pos == 3) {
            resultList.add(resultString);
            return;
        }
        for (int i = 0; i < 3; ++i) {
            if (!resultString.contains(String.valueOf(s[i]))) {
                computeResult(s, pos + 1, resultString + s[i]);
            }
        }
    }

    public static void main(String... args) {
        Scanner sc = new Scanner(System.in);
        char[] s = sc.next().toCharArray();
        sc.close();
        computeResult(s, 0, "");
        for(String str : resultList) {
            System.out.println(str);
        }
    }
}

说明:

递归由computeResult函数完成。它以空字符串开头,然后遍历所有可能的字母“ c”,“ a”和“ t”,并将它们附加到resultString上,现在有3个字符串,并且每个字符串都有函数computeResult再次被调用。然后,它执行相同的操作,并且仅将尚未添加的那些字母添加到resultString中,因此在“ c”中,我们附加“ a”,从而导致“ ca”和“ t”,从而导致“ ct”,我想想剩下的你可以弄清楚自己。

请注意,如果字母是唯一的,则可以这样做。如果没有,例如,给您提供字符串“ tat”,则可以将其转换为t1a1t2,并对数组['t1','a1','t2']执行相同的过程,然后删除数字。 / p>

答案 1 :(得分:1)

我使用的算法非常简单。将每个字符设为字符串的第一个字符,然后查找与其他两个字符的组合。因此,对于字符c,a,t,组合为

c at
c ta

a ct
a tc

t ca
t ac

代码:

static void findWords(String str, int pos) {
    if(str == null || pos < -1) {
        return;
    }

    int len = str.length();
    if(pos + 1 < len) {
        findWords(str, pos + 1);
    }

    //find char swap positions
    int pos1 = (pos + 1) % len;
    int pos2 = (pos - 1 + len) % len;

    char[] chars = str.toCharArray();
    String str1 = new String(new char[] {chars[pos], chars[pos1], chars[pos2]});
    String str2 = new String(new char[] {chars[pos], chars[pos2], chars[pos1]});

    System.out.println(str1);
    System.out.println(str2);
}

public static void main(String[] args) {
    String word = new String("abc");
    findWords(word, 0);
}

答案 2 :(得分:0)

这是一个完整的工作示例,上面有我的评论来解释算法。

此解决方案基于回溯。详细了解该here。把问题看成一棵树。在您的示例中,单词是“ cat”。这里有一些ascii艺术...

                                      cat
                              /        |        \
                            Cat       Act       Tca 
                           /   \     /   \     /   \
                          CAt CTa   ACt ATc   TCa TAc

每次通过时,您都要固定一个字母(我把它写为大写)。树越深,交换就越少,因为您已经固定了一定数量的字母(在级别0,什么都没有固定,在级别1,一个字母是固定的,所以可以进行交换,在第2级,您不再有交换(交换将与它本身进行),因此递归达到其基本情况。

public static void main(String[] args) {
    // get all the permutations of a word with distinct letters
    Set<String> permutations = getPermutations("cat");

    // print the resulting set
    System.out.println(permutations);
}

private static Set<String> getPermutations(String string) {
    // recursive call to get a permutation of the given string and put it in
    // the set of permutations (initially empty)
    return permute(string, 0, string.length() - 1, new HashSet<String>());
}

private static Set<String> permute(String string, int left, int right, Set<String> set) {
    if (left == right) {
        // swap would be with itself so just add the string
        // this is the base case
        set.add(string);
    } else {
        for (int i = left; i <= right; i++) {
            // indices are different, something can be swapped so swap it
            string = swap(string, left, i);
            // permute the swapped string starting from the next available character
            permute(string, left + 1, right, set);
        }
    }
    return set;
}

// utility method to carry out the swapping
// you could do this with primitive char[] and probably improve performance
// but for the sake of simplicity as it's just an exercise I used a 
// StringBuilder
private static String swap(String in, int i, int j) {
    char tmp1 = in.charAt(i);
    char tmp2 = in.charAt(j);
    StringBuilder sb = new StringBuilder(in);
    // put the char at j in place of the char at i
    sb.setCharAt(i, tmp2);
    // and do the same the other way around
    sb.setCharAt(j, tmp1);

    return sb.toString();
}