Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 查找单词中非重复字母的所有排列_Java_Algorithm_Recursion - Fatal编程技术网

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

Java 查找单词中非重复字母的所有排列,java,algorithm,recursion,Java,Algorithm,Recursion,给定3个唯一的字母:你能用递归函数打印出6个可能的非重复字母组合吗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.ou

给定3个唯一的字母:你能用递归函数打印出6个可能的非重复字母组合吗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);
}
静态void findWords(StringBuilder字符串、int start、int stride){
//1.递归地遍历所有可能的字符组合
System.out.println(字符串);
如果(步幅
解决方案:

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);
        }
    }
}
import java.util.ArrayList;
导入java.util.List;
导入java.util.Scanner;
公共班机{
静态列表resultList=new ArrayList();
静态void computeResult(char[]s,int pos,String resultString){
如果(位置==3){
添加(resultString);
返回;
}
对于(int i=0;i<3;++i){
如果(!resultString.contains(String.valueOf(s[i])){
计算机结果(s,pos+1,resultString+s[i]);
}
}
}
公共静态void main(字符串…参数){
扫描仪sc=新的扫描仪(System.in);
char[]s=sc.next().toCharArray();
sc.close();
计算机结果(s,0,“”);
for(字符串str:resultList){
系统输出打印项次(str);
}
}
}
说明:

递归由
computeResult
函数完成。它以一个空字符串开始,然后遍历所有可能的字母“c”、“a”和“t”,将它们附加到resultString中,现在有3个字符串,每个字符串都会再次调用函数
ComputerResult
。然后它做同样的事情,并且只将那些尚未添加的字母添加到resultString中,因此在“c”中添加“a”,结果是“ca”和“t”,结果是“ct”,我想剩下的你可以自己解决


请注意,如果字母是唯一的,则此选项不起作用。如果不是,例如,您得到字符串“tat”,您可以将其转换为t1a1t2,并对数组['t1',a1',t2']执行相同的过程,然后删除数字。

我使用的算法非常简单。使每个字符成为字符串的第一个字符,并找到与其他两个字符的组合。所以对于字符c,a,t的组合是

c at
c ta

a ct
a tc

t ca
t ac
代码:

静态void findWords(字符串str,int pos){
如果(str==null | | pos<-1){
返回;
}
int len=str.length();
如果(位置+1
下面是一个完整的工作示例,我用自己的注释解释算法

此解决方案基于回溯。阅读更多关于这方面的信息。把问题看成一棵树。在你的例子中,单词是“猫”。这里有一些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();
}
publicstaticvoidmain(字符串[]args){
//获取一个单词的所有不同字母排列
Set permutations=getPermutations(“cat”);
//打印结果集
System.out.println(置换);
}
私有静态集getPermutations(字符串){
//递归调用以获取给定字符串的排列并将其放入
//排列集(最初为空)
返回置换(string,0,string.length()-1,newhashset());
}
私有静态集合置换(字符串字符串、左整数、右整数、集合){
如果(左==右){
//swap本身就是一个函数,所以只需添加字符串即可
//这是基本情况
set.add(字符串);
}否则{

对于(int i=left;谢谢,我认为这可以通过纯递归来实现,就像在获取所有可能性时一样,但这看起来做得很好,而且很有效。@MGT你说的“纯递归”是什么意思?我现在明白了这不是真的可能,而是“纯递归”我的意思是在不将结果存储在数组中的情况下解决这个问题,只是让递归调用计算出所有的排列,并且不重复地显示它们。@MGT有什么问题吗?您可以删除
resultList.add(resultString);
行,并将其替换为
System.out.println(resultString)
。我只将结果存储在该列表中,以便以后能够在main中输出它们……这是一个优秀的实现。它可以计算任意长度的单词。我仍在按照“框”中的“框”进行递归思考。但要递归思考,我首先需要递归思考,当然。
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();
}