具有n個元素的集合的子集數爲2 n。例如,如果我們有字符串「abc」,那麼我們將有2個子集,其中有2個是子組。
可以用n位表示的狀態數也是2 n。我們可以顯示有用於枚舉n位和所有可能的狀態的所有可能的子集對一組具有n個元素之間的對應關係:
2 1 0 2 1 0
c b a bits
0 0 0 0
1 a 0 0 1
2 b 0 1 0
3 b a 0 1 1
4 c 1 0 0
5 c a 1 0 1
6 c b 1 1 0
7 c b a 1 1 1
如果我們考慮第5行,例如,位2和0是活動的。如果我們做abc.charAt(0) + abc.charAt(2)
,我們得到子集ac
。
要列舉爲我們從0開始的n比特的所有可能的狀態,和一個求和直到我們達到2 Ñ - 1。在該溶液中,我們將在2 Ñ開始 - 1和遞減直到0,所以我們不需要另外的參數,只是爲了保持亞羣的數量,但效果是一樣的:
static List<String> powerSet(String s) {
// the number of subsets is 2^n
long numSubsets = 1L << s.length();
return powerSet(s, numSubsets - 1);
}
static List<String> powerSet(String s, long active) {
if (active < 0) {
// Recursion base case
// All 2^n subsets were visited, stop here and return a new list
return new ArrayList<>();
}
StringBuilder subset = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
// For each bit
if (isSet(active, i)) {
// If the bit is set, add the correspondent char to this subset
subset.append(s.charAt(i));
}
}
// Make the recursive call, decrementing active to the next state,
// and get the returning list
List<String> subsets = powerSet(s, active - 1);
// Add this subset to the list of subsets
subsets.add(subset.toString());
return subsets;
}
static boolean isSet(long bits, int i) {
// return true if the ith bit is set
return (bits & (1L << i)) != 0;
}
然後你只需要調用它:
System.out.println(powerSet("abc"));
,並得到所有8子集:
[, a, b, ab, c, ac, bc, abc]
可能重複[爪哇 - 使用遞歸來創建一個字符串的所有子(http://stackoverflow.com/questions/18280442/java-using-recursion-to-create-all-字符串子字符串) – ruhungry
該代碼不能正確處理空字符串的邊緣情況。所以,如果你用空字符串調用它,它會返回空字符串。 –
我想我知道現在是什麼問題,但我不知道如何解決它。目前,我發現所有的電源設置爲「bcd」,「acd」,「abd」,「abc」,這會導致重複。有想法該怎麼解決這個嗎? – Tim223