问题
I want to perform a variation of a "6 choose 2" operation. I have written the following code.
public void choosePatterns(){
String[] data = {"1", "2", "3", "4", "5", "6"};
String[] originalPattern = new String[15];
int index = 0;
for(int i = 0; i < (6-1); i++)
{
for(int j = i+1; j < 6; j++)
{
System.out.println(i + "," +j);
}
}
}
My code so far generates all the possible combinations of "6 choose 2." However, I would like to vary this and print all the remaining numbers. So far instance, if one of the combinations of "6 choose 2" is "3" and "4," then I would like to print "1," "2," "5," "6."
I am not sure how to most efficiently do this. The long-winded way would be to delete those indices in the "data" array, shift the data so there aren't gaps, then print the array. But is there a faster, more efficient way to do this?
回答1:
Here's a way to do it.
public static void choosePatterns(int total, int toChoose) {
List<Integer> indices = IntStream.range(1, toChoose + 1).mapToObj(i -> Integer.valueOf(0)).collect(Collectors.toList());
resetIndex(indices, 0, 1, total);
while (true) {
System.out.println("chosen: " + indices);
System.out.print("not chosen: ");
for (int i = 1; i <= total; i++) {
if (! indices.contains(Integer.valueOf(i))) {
System.out.print(i + " ");
}
}
System.out.println("\n");
if (! incrementIndices(indices, indices.size() - 1, total)) {
break;
}
}
}
public static boolean resetIndex(List<Integer> indices, int posn, int value, int total) {
if (value <= total) {
indices.set(posn, value);
return posn == indices.size() - 1 ? true : resetIndex(indices, posn + 1, value + 1, total);
} else {
return false;
}
}
public static boolean incrementIndices(List<Integer> indices, int posn, int total) {
if (indices.get(posn) < total) {
indices.set(posn, indices.get(posn) + 1);
} else {
int resetPosn = posn;
do {
if (resetPosn-- == 0) return false;
} while (! resetIndex(indices, resetPosn, indices.get(resetPosn) + 1, total));
}
return true;
}
public static void main(String[] args) throws IOException {
choosePatterns(6, 2);
}
It prints this:
chosen: [1, 2]
not chosen: 3 4 5 6
chosen: [1, 3]
not chosen: 2 4 5 6
chosen: [1, 4]
not chosen: 2 3 5 6
chosen: [1, 5]
not chosen: 2 3 4 6
chosen: [1, 6]
not chosen: 2 3 4 5
chosen: [2, 3]
not chosen: 1 4 5 6
chosen: [2, 4]
not chosen: 1 3 5 6
chosen: [2, 5]
not chosen: 1 3 4 6
chosen: [2, 6]
not chosen: 1 3 4 5
chosen: [3, 4]
not chosen: 1 2 5 6
chosen: [3, 5]
not chosen: 1 2 4 6
chosen: [3, 6]
not chosen: 1 2 4 5
chosen: [4, 5]
not chosen: 1 2 3 6
chosen: [4, 6]
not chosen: 1 2 3 5
chosen: [5, 6]
not chosen: 1 2 3 4
回答2:
I changed to using an array of ints, and just added 1 to the values for display purposes:
public static void choosePatterns(){
int[] display = new int[6];
for(int i = 0; i < (6-1); i++)
{
for(int j = i+1; j < 6; j++)
{
display[0] = i+1;
display[1] = j+1;
int x = 2;
for(int k = 0; k < 6; k++)
{
if((k != i) && (k != j))
display[x++] = k+1;
}
System.out.println(Arrays.toString(display));
}
}
}
回答3:
Well, since you want [6 choose X] to become dynamic (X = 2, 3, 4,..) and don't want to add a specific number of for-loops for every case, I think recursion should do the trick.
Let's see following sample code:
public void choosePatterns(){
String[] data = {"1", "2", "3", "4", "5", "6"};
int deep = 3; // << This value is the X above
deep = deep > data.length ? data.length : deep; // << prevent X over data length
printCombine(data, new ArrayList<Integer>(), deep); // Main business here
}
printCombine method content:
private void printCombine(final String[] data, final List<Integer> selectedIdxs, final int deep) {
if(deep == 1) { // When come to the last combine number, print out
StringBuilder sb = new StringBuilder();
for(int i : selectedIdxs) {
sb.append(data[i]);
sb.append(", ");
}
String prefixCombine = sb.toString();
for(int i = 0; i < data.length; i++) {
if(!selectedIdxs.contains(i)) {
System.out.println(new StringBuilder(prefixCombine).append(data[i]).toString());
}
}
} else {
for(int i = 0; i < data.length; i++) {
if(!selectedIdxs.contains(i)) {
// Mark the selected indices of the combination
List<Integer> curSelectedIdx = new ArrayList<Integer>();
curSelectedIdx.addAll(selectedIdxs);
curSelectedIdx.add(i);
printCombine(data, curSelectedIdx, deep - 1);
}
}
}
}
来源:https://stackoverflow.com/questions/39400073/generating-the-combinations-of-a-choose-operation