Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/222.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_Combinations - Fatal编程技术网

Java 生成字符串的所有组合的算法

Java 生成字符串的所有组合的算法,java,algorithm,combinations,Java,Algorithm,Combinations,我在网上找到了一个链接,显示了生成字符串所有组合的算法: 算法复制如下 void combine(String instr, StringBuffer outstr, int index) { for (int i = index; i < instr.length(); i++) { outstr.append(instr.charAt(i)); System.out.println(outstr); combine(ins

我在网上找到了一个链接,显示了生成字符串所有组合的算法:

算法复制如下

void combine(String instr, StringBuffer outstr, int index)
{
    for (int i = index; i < instr.length(); i++)
    {
        outstr.append(instr.charAt(i));
        System.out.println(outstr);
        combine(instr, outstr, i + 1);
        outstr.deleteCharAt(outstr.length() - 1);
    }
} 

combine("abc", new StringBuffer(), 0);

如果我删除这一行,程序显然不再工作,但为什么首先需要这样做?我理解递归的思想,即我们改变一个初始字符并对其余字符进行递归,但是deleteChar行似乎在逻辑上不适合任何地方。添加outtr.deleteCharAt行的原因是什么?

它平衡循环体的第一行,将outtr恢复到循环体顶部的状态(通过从追加的instr中删除字符)

调用
outtr.deleteCharAt
通过删除
outtr
的最后一个字符来抵消
outtr.append
的效果

每个循环迭代按如下方式进行:

  • 附加字符
  • 打印结果
  • i+1级别执行递归调用
  • 删除我们在步骤1中添加的角色

  • 这很符合逻辑。你看,我们这里有一个递归算法。在position
    i
    中的每个步骤中,我们放置字符串的一个字母,然后递归调用函数,将另一个字母放置在下一个位置。然而,当我们从递归返回时,我们需要删除最初放置的字符,以便我们可以用序列中下一个可能的字符替换它。例如:

    append a on pos 0 -> a
    call recursion
    append a on pos 1 -> aa
    call recursion
    append a on pos 2 -> aaa
    return from recursion
    remove a from pos 2 -> aa
    append b on pos 2 -> aab
    return from recursion
    remove b from pos 2 -> aa
    append c on pos 2 -> aac
    etc.
    
    意味着你有

    n^(n-1)/2 pairs of combinations.
    
    迭代for循环不会在递归函数调用后停止,因此您需要删除输出缓冲区中的最后一个字符,因为您不希望

    n^n/2 pairs of combinations.
    

    在图论中,这是一个短路

    计算字符串可能组合的最简单方法是

    用数学方法在给定批次的N=NcR中找到R个组合

    所以我们在这里发现的是,所有可能的组合=Nc0+Nc1….+Ncn=2功率N

    因此,对于给定的长度为N个字符的单词,可以得到2个Pow N组合

    如果你用二进制表示1到2个整数,把你的字符放在1出现的地方,最后你会得到答案

    例子: 输入:ABC

    解决方案:

    ABC长度是3。因此,可能的组合2功率3=8

    如果0-8用二进制表示

    000=

    001=C

    010=B

    011=BC

    100=A

    101=交流电

    110=AB

    111=ABC


    上面显示了所有可能的组合。

    下面的代码是生成字符串的排列和组合,基本上是一次选择一个字符:

    public class permutecombo
    {
      static void initiate(String s)
      {
        permute("", s);
        System.out.println("----------------------------------------- ");
        combo("", s);
        System.out.println("----------------------------------------- ");
      }
    
      static void combo(String prefix, String s)
      {
        int N = s.length();
    
        System.out.println(prefix);
    
        for (int i = 0 ; i < N ; i++)
          combo(prefix + s.charAt(i), s.substring(i+1));
      }
      static void permute(String prefix, String s)
      {
        int N = s.length();
    
        if (N == 0)
          System.out.println(" " + prefix);
    
        for (int i = 0 ; i < N ; i++)
          permute(prefix + s.charAt(i), s.substring(0, i) + s.substring(i+1, N));
      }
    
      public static void main(String[] args)
      {
        String s = "1234";
        initiate(s);
      }
    }
    
    公共类permutecombo
    {
    静态无效初始化(字符串s)
    {
    排列(“,s);
    System.out.println(“--------------------------------------------------------”;
    组合(“,s);
    System.out.println(“--------------------------------------------------------”;
    }
    静态无效组合(字符串前缀,字符串s)
    {
    int N=s.长度();
    System.out.println(前缀);
    对于(int i=0;i
    我们可以使用前面提到的位概念来生成字符串的所有子字符串。这里是代码(C++中,但你知道)这样做:-<
    string s;
    int n = s.size();
    int num = 1<<n;
    for(int i =1; i< num ; i++){ //Checks all the permutations.
        int value = i;
        int j, pos;
        for (j=1, pos=1; j < num; j<<=1, pos++) //Finds the bits that are set
            if (i & j)
                cout<<s[pos-1]; //You can print s[n-pos] to print according to bit position
        cout<<endl;        
    }
    
    字符串s;
    int n=s.size();
    int num=1
    //如果需要重复,请使用ARRAYLIST而不是SET!!
    导入java.util.*;
    公共类置换{
    公共静态void main(字符串[]args){
    扫描仪输入=新扫描仪(系统输入);
    System.out.println(“输入字符串”);
    Set se=find(在.nextLine()中);
    系统输出println((se));
    }
    公共静态集查找(字符串s)
    {
    Set ss=新的HashSet();
    如果(s==null)
    {
    返回null;
    }
    如果(s.length()==0)
    {
    ss.加入(“);
    }
    其他的
    {
    字符c=s.charAt(0);
    字符串st=s.子字符串(1);
    设置qq=find(st);
    用于(字符串str:qq)
    {
    
    对于(int i=0;i这里是C++代码,没有OP问题中的棘手回溯步骤。

    #include <iostream>
    #include <string>
    using namespace std;
    static const string in("abc");
    void combine(int i, string out)
    {
        if (i==in.size()) {
            cout << out << endl;
            return;
        }
        combine(i+1, out);
        combine(i+1, out+in[i]);
    }
    
    int main()
    {
        combine(0, "");
        return 0;
    }
    
    #包括
    #包括
    使用名称空间std;
    “abc”中的静态常量字符串;
    无效合并(整数i,字符串out)
    {
    如果(i==in.size()){
    
    非常感谢!这使理解解决方案变得更容易。太棒了!我相信这是最直观的实现方法。它没有BA、CA、CBA……和其他字符串,我想它们是可能的,不同的字符串。因为我们需要所有的组合,有字符(I)和没有字符(I),我们需要将这两种情况分开。那些没有字符(I)的组合在for循环的下一次迭代中,通过在当前迭代结束之前使用deleteCharAt()的魔力来处理。
    string s;
    int n = s.size();
    int num = 1<<n;
    for(int i =1; i< num ; i++){ //Checks all the permutations.
        int value = i;
        int j, pos;
        for (j=1, pos=1; j < num; j<<=1, pos++) //Finds the bits that are set
            if (i & j)
                cout<<s[pos-1]; //You can print s[n-pos] to print according to bit position
        cout<<endl;        
    }
    
     The size is 3  . So we check from 1 to 7 ( 1<<3).
     for i = 1 ( 001 ) , the first bit is set, so a is printed.
     for i = 2 ( 010 ) , the second bit is set, so b is printed.
     for i = 3 ( 011 ) , the first and second bit are set, so ab is printed.
     .
     .
     .
     for i = 7 ( 111 ) , all three bits are set, so abc is printed.
    
    // IF YOU NEED REPEATITION USE ARRAYLIST INSTEAD OF SET!!
    
    import java.util.*;
    public class Permutation {
    
        public static void main(String[] args) {
            Scanner in=new Scanner(System.in);
            System.out.println("ENTER A STRING");
            Set<String> se=find(in.nextLine());
            System.out.println((se));
        }
        public static Set<String> find(String s)
        {
            Set<String> ss=new HashSet<String>();
            if(s==null)
            {
                return null;
            }
            if(s.length()==0)
            {
                ss.add("");
            }
            else
            {
                char c=s.charAt(0);
                String st=s.substring(1);
                Set<String> qq=find(st);
                for(String str:qq)
                {
                    for(int i=0;i<=str.length();i++)
                    {
                        ss.add(comb(str,c,i));
                    }
                }
            }
            return ss;
    
        }
        public static String comb(String s,char c,int i)
        {
            String start=s.substring(0,i);
            String end=s.substring(i);
            return start+c+end;
        }
    
    }
    
    
    // IF YOU NEED REPEATITION USE ARRAYLIST INSTEAD OF SET!!
    
    #include <iostream>
    #include <string>
    using namespace std;
    static const string in("abc");
    void combine(int i, string out)
    {
        if (i==in.size()) {
            cout << out << endl;
            return;
        }
        combine(i+1, out);
        combine(i+1, out+in[i]);
    }
    
    int main()
    {
        combine(0, "");
        return 0;
    }
    
    import com.google.common.collect.Lists;
    
    import java.util.List;
    
    public class Combinations {
        public static String[] getCombinations(final String input) {
            final List<String> combinations = Lists.newArrayList();
            getCombinations(input.toCharArray(), combinations, 0, "");
            return combinations.toArray(new String[0]);
        }
    
        private static void getCombinations(final char[] input, final List<String> combinations, final int index, final String combination) {
            if (index == input.length) {
                combinations.add(combination);
                return;
            }
            getCombinations(input, combinations, index + 1, combination + String.valueOf(input[index]));
            getCombinations(input, combinations, index + 1, combination);
        }
    
    }
    
    import org.hamcrest.Matchers;
    import org.junit.Test;
    
    import static org.hamcrest.MatcherAssert.assertThat;
    
    public class CombinationsTest {
        @Test
        public void testCombinations() {
            verify(Combinations.getCombinations(""), "");
            verify(Combinations.getCombinations("a"), "a", "");
            verify(Combinations.getCombinations("ab"), "ab", "a", "b", "");
            verify(Combinations.getCombinations("abc"), "abc", "ab", "ac", "a", "bc", "b", "c", "");
            verify(Combinations.getCombinations("abcd"),
                    "abcd", "abc", "abd", "ab", "acd", "ac", "ad", "a", "bcd", "bc", "bd", "b", "cd", "c", "d", "");
        }
    
        private void verify(final String[] actual, final String... expected) {
            assertThat(actual, Matchers.equalTo(expected));
        }
    }