我想要一个代码来生成给定字符串的所有字符串子集。
我自己尝试了这个并提出了这个:
public static void main(String[] args){
long startTime = System.nanoTime();
String text = "1234";
int n = text.length();
String k = "";
for(int i=0;i < Math.pow(2, n);i++){
k = Integer.toBinaryString(i);
while(k.length() != n){
k = "0"+k;
}
StringBuilder sb = new StringBuilder();
for(int j=0;j<k.length();j++){
if(k.charAt(j) == '1'){
sb.append(text.charAt(j));
}
}
// System.out.println(String.format("%04d",
// Integer.parseInt(k)));
System.out.println(sb.toString());
}
long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println("Duration:" + duration);
}
但这是一个可怕的O(n ^ 2)算法,所以我一直在寻找更好的解决方案,并发现了这个:
public static void comb2(String s) {
comb2("", s);
}
private static void comb2(String prefix, String s) {
System.out.println(prefix);
for (int i = 0; i < s.length(); i++){
comb2(prefix + s.charAt(i), s.substring(i + 1));
}
}
// read in N from command line, and print all subsets among N elements
public static void main(String[] args) {
String alphabet = "1234";
comb2(alphabet);
System.out.println();
}
生成的输出是: 1 12 123 1234 124 13 134 14 2 23 234 24 3 34 4
虽然代码工作正常。我正在调试它以理解逻辑。我得到了如何生成1,12,123,1234,但之后不太清楚。能告诉我这里发生了什么吗?
答案 0 :(得分:1)
您需要了解的是comb2方法的工作原理。基本上,它自称。这称为递归。
当您拨打comb2(&#34; 1234&#34;)时,结果是对comb2的调用(&#34;&#34;,&#34; 1234&#34;)。
这是你从&#34; 1234&#34;至&#34; 124&#34;。希望,从那里,你应该能够理解整个执行过程。
答案 1 :(得分:0)
关键点是comb2(prefix + s.charAt(i), s.substring(i + 1))
,为了更好地理解它,请用笛卡尔积的这个陈述进行类比,我认为这解决了所有问题。实际上,您可以创建所有以字符串开头的子字符串。
答案 2 :(得分:0)
这是一个时刻的涂鸦给我带来的:
import java.util.List;
import java.util.LinkedList;
public class subs {
static List<String> allInitialSubstrings(String s) {
List<String> r = new LinkedList<String>();
for (int i=0; i<s.length(); i++) {
r.add(s.substring(0, i+1));
}
return r;
}
static List<String> allSubstrings(String s) {
List<String> r = new LinkedList<String>();
for (int i=0; i<s.length(); i++) {
r.addAll(allInitialSubstrings(s.substring(i)));
}
return r;
}
public static void main(String ... args) {
System.out.println(allSubstrings(args[0]));
}
}
~ $ javac subs.java
~ $ java subs 12345
[1, 12, 123, 1234, 12345, 2, 23, 234, 2345, 3, 34, 345, 4, 45, 5]
如果你想要子集而不是子串,那么用Java这样的古老语言来编写它是一件非常痛苦的事情,但是这里只是一个稍微老一点的Python:
def allSubsets(s):
if len(s):
car = s[0]
cdr = allSubsets(s[1:])
return set([car + b for b in cdr]).union(cdr)
else:
return set([""])
allSubsets("12345")
答案 3 :(得分:0)
此程序应该可以正常工作
public static void getAllSubStrings(char[] chars,int start, Set allSubStrings){
StringBuilder sb = new StringBuilder();
if(start==chars.length){
return;
}
for(int i=start;i<chars.length;i++){
sb.append(chars[i]);
allSubStrings.add(sb.toString());
}
getAllSubStrings(chars, start+1, allSubStrings);
}
public static void main(String[] args) {
Set s = new TreeSet();
getAllSubStrings("12345".toCharArray(), 0, s);
System.out.println(s);
}
生成的输出为[1, 12, 123, 1234, 12345, 2, 23, 234, 2345, 3, 34, 345, 4, 45, 5]
从我认为这仍然是O(n2),因为它将运行n +(n-1)+(n-2)......次数是n(n + 1)/ 2我不&# 39;认为你可以比那更好
答案 4 :(得分:0)
没有任何for循环,具有相同逻辑的更干净的版本将是:
public static void printSubSets(String s){
subSetsHelper(s, "");
}
private static void subSetsHelper(String s, String acc) {
if (s.equals("")){
System.out.println(acc);
return;
}
subSetsHelper(s.substring(1), acc + s.charAt(0)); // accumulate 1st character
subSetsHelper(s.substring(1), acc); // do not
}
printSubSets(“ abc”); abc b 交流电 一种 公元前 b C “”