Вы можете использовать рекурсию, «угадать», если первый пакет находится в комбинации или нет - и вызывать рекурсивно без первого пакета.
Псевдо-код:
combinations(packages, sol):
if (packages.length == 0): //base clause
print sol
return
package <- packages.first //1 possibility: the first package is in the combination
packages.removeFirst()
sol.append(package)
combinations(packages,sol) //recursively invoke without the first package
sol.removeLast() //clean up environment - remove the last added package
combinations(packages,sol) //2nd possibility: the first package is not in the combination
Примечания:
- Предполагается, что пустое решение [пакет не был выбран] также является возможным вариантом в этом алгоритме - если это не так, его можно легко обработать в предложении base.
- Предполагается, что порядок не важен. Package1 AND Package2 - это то же самое, что Package2 AND Package1.
- Существует
2^n
возможных комбинаций для выбора пакетов, поэтому любому алгоритму, который выполняет то, что вы просите [включая этот], потребуется O(2^n)
время, поэтому я бы не стал вызывать этот алгоритм с 100 пакетами ... .
В Java это может выглядеть примерно так:
public static void printCombinations(LinkedList<String> packages, LinkedList<String> sol) {
if (packages.size() == 0) {
System.out.println(sol);
return;
}
String pack = packages.poll(); //also removes the head
sol.addLast(pack);
printCombinations(new LinkedList(packages),sol);
sol.removeLast();
printCombinations(new LinkedList(packages),sol);
}
и вызов по:
printCombinations(packages, new LinkedList<String>());
Где packages
- это LinkedList
со всеми вашими пакетами.
- Я использовал
LinkedList
для packages
и создал новые объекты, потому что я
найти более понятным. Для повышения производительности - вы можете использовать один
массив с index
[который будет изменен между рекурсивными вызовами] в
чтобы не повторять packages
столько раз.