forked from williamfiset/Algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CombinationsWithRepetition.java
92 lines (76 loc) · 2.74 KB
/
CombinationsWithRepetition.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/**
* Here I show how you can generate all the combinations of a sequence of size r which are repeated
* at most k times.
*
* <p>Time Complexity: O(n+r-1 choose r) = O((n+r-1)!/(r!(n-1)!))
*
* @author William Fiset, william.alexandre.fiset@gmail.com
*/
package com.williamfiset.algorithms.other;
public class CombinationsWithRepetition {
/**
* Computes all combinations of elements of 'r' elements which can be repeated at most 'k' times
* each.
*
* @param sequence - The sequence containing all the elements we wish to take combinations from
* @param usedCount - Tracks how many of each element we currently have selected
* @param at - The current position we're at in the sequence
* @param r - The number of elements we're choosing
* @param k - The maximum number of times each element is allowed to be picked
*/
private static void combinationsWithRepetition(
int[] sequence, int[] usedCount, int at, int r, int k) {
final int N = sequence.length;
// We reached the end
if (at == N) {
// We selected 'r' elements in total
if (r == 0) {
// Print combination
System.out.print("{ ");
for (int i = 0; i < N; i++)
for (int j = 0; j < usedCount[i]; j++) System.out.print(sequence[i] + " ");
System.out.println("}");
}
} else {
// For this particular time at position 'at' try including it each of [0, k] times
for (int itemCount = 0; itemCount <= k; itemCount++) {
// Try including this element itemCount number of times (this is possibly more than once)
usedCount[at] = itemCount;
combinationsWithRepetition(sequence, usedCount, at + 1, r - itemCount, k);
}
}
}
// Given a sequence this method prints all the combinations of size
// 'r' in a given sequence which has each element repeated at most 'k' times
public static void printCombinationsWithRepetition(int[] sequence, int r, int k) {
if (sequence == null) return;
final int n = sequence.length;
if (r > n) throw new IllegalArgumentException("r must be <= n");
if (k > r) throw new IllegalArgumentException("k must be <= r");
int[] usedCount = new int[sequence.length];
combinationsWithRepetition(sequence, usedCount, 0, r, k);
}
public static void main(String[] args) {
// Prints all combinations of size 3 where
// each element is repeated at most twice
int[] seq = {1, 2, 3, 4};
printCombinationsWithRepetition(seq, 3, 2);
// prints:
// { 3 4 4 }
// { 3 3 4 }
// { 2 4 4 }
// { 2 3 4 }
// { 2 3 3 }
// { 2 2 4 }
// { 2 2 3 }
// { 1 4 4 }
// { 1 3 4 }
// { 1 3 3 }
// { 1 2 4 }
// { 1 2 3 }
// { 1 2 2 }
// { 1 1 4 }
// { 1 1 3 }
// { 1 1 2 }
}
}