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级别执行递归调用
这很符合逻辑。你看,我们这里有一个递归算法。在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));
}
}