当n = 5且k = 3时,以下循环将执行此操作
List<String> l=new ArrayList<String>();
l.add("A");l.add("B");l.add("C");l.add("D");l.add("E");
int broadcastSize = (int) Math.pow(2, l.size());
for (int i = 1; i < broadcastSize; i++) {
StringBuffer buffer = new StringBuffer(50);
int mask = i;
int j = 0;
int size=0;
System.out.println();
while (mask > 0) {
if ((mask & 1) == 1) {
System.out.println(".. "+mask);
buffer.append(l.get(j));
if (++size>3){
buffer = new StringBuffer(50);
break;
}
}
System.out.println(" "+mask);
mask >>= 1;
j++;
}
if (buffer.length()>0)
System.out.println(buffer.toString());
}
但效率不高我想用Banker's sequence来做,然后探索第一个单身,然后是对,然后是3元组并停止。
我没有找到办法,但至少这个循环应该更有效:
List<String> l=new ArrayList<String>();
l.add("A");l.add("B");l.add("C");l.add("D");l.add("E");
int broadcastSize = (int) Math.pow(2, l.size());
for (int i = 1; i < broadcastSize; i++) {
StringBuffer buffer = new StringBuffer(50);
int mask = i;
int j = 0;
if (StringUtils.countMatches(Integer.toBinaryString(i), "1") < 4){
while (mask > 0) {
if ((mask & 1) == 1) {
buffer.append(l.get(j));
}
mask >>= 1;
j++;
}
if (buffer.length()>0)
System.out.println(buffer.toString());
}
}
还有:但是k嵌入式循环看起来很难看
//singleton
for (int i = 0; i < l.size(); i++) {
System.out.println(l.get(i));
}
//pairs
for (int i = 0; i < l.size(); i++) {
for (int j = i+1; j < l.size(); j++) {
System.out.println(l.get(i)+l.get(j));
}
}
//3-tuple
for (int i = 0; i < l.size(); i++) {
for (int j = i+1; j < l.size(); j++) {
for (int k = j+1; k < l.size(); k++) {
System.out.println(l.get(i)+l.get(j)+l.get(k));
}
}
}
//...
// k-tuple
答案 0 :(得分:4)
此技术称为Gosper's hack。它仅适用于n <= 32
,因为它使用int
的位,但如果您使用long
,则可以将其增加到64。
int nextCombo(int x) {
// moves to the next combination with the same number of 1 bits
int u = x & (-x);
int v = u + x;
return v + (((v ^ x) / u) >> 2);
}
...
for (int x = (1 << k) - 1; (x >>> n) == 0; x = nextCombo(x)) {
System.out.println(Integer.toBinaryString(x));
}
对于n = 5
和k = 3
,会打印
111
1011
1101
1110
10011
10101
10110
11001
11010
11100
完全按照你的预期完成。
答案 1 :(得分:2)
这应该是最有效的方法,即使k嵌入式循环看起来很丑陋
//singleton
for (int i = 0; i < l.size(); i++) {
System.out.println(l.get(i));
}
//pairs
for (int i = 0; i < l.size(); i++) {
for (int j = i+1; j < l.size(); j++) {
System.out.println(l.get(i)+l.get(j));
}
}
//3-tuple
for (int i = 0; i < l.size(); i++) {
for (int j = i+1; j < l.size(); j++) {
for (int k = j+1; k < l.size(); k++) {
System.out.println(l.get(i)+l.get(j)+l.get(k));
}
}
}
// ...
//k-tuple
答案 2 :(得分:0)
Apache commons具有大小为k的subsets和permutations的迭代器。 这是一个迭代器,它遍历n元组的1-k元组,它结合了两者:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.collections4.iterators.PermutationIterator;
import org.apache.commons.math3.util.Combinations;
public class AllTuplesUpToKIterator implements Iterator<List<Integer>> {
private Iterator<int[]> combinationIterator;
private PermutationIterator<Integer> permutationIterator;
int i;
int k;
int n;
public AllTuplesUpToKIterator(int n, int k) {
this.i = 1;
this.k = k;
this.n = n;
combinationIterator = new Combinations(n, 1).iterator();
permutationIterator = new PermutationIterator<Integer>(intArrayToIntegerList(combinationIterator.next()));
}
@Override
public boolean hasNext() {
if (permutationIterator.hasNext()) {
return true;
} else if (combinationIterator.hasNext()) {
return true;
} else if (i<k) {
return true;
} else {
return false;
}
}
@Override
public List<Integer> next() {
if (!permutationIterator.hasNext()) {
if (!combinationIterator.hasNext()) {
i++;
combinationIterator = new Combinations(n, i).iterator();
}
permutationIterator = new PermutationIterator<Integer>(intArrayToIntegerList(combinationIterator.next()));
}
return permutationIterator.next();
}
@Override
public void remove() {
// TODO Auto-generated method stub
}
public static List<Integer> intArrayToIntegerList(int[] arr) {
List<Integer> result = new ArrayList<Integer>();
for (int i=0; i< arr.length; i++) {
result.add(arr[i]);
}
return result;
}
public static void main(String[] args) {
int n = 4;
int k = 2;
for (AllTuplesUpToKIterator iter= new AllTuplesUpToKIterator(n, k); iter.hasNext();) {
System.out.println(iter.next());
}
}
}