减治法在生成组合对象问题中的应用
生成子集问题:经典的背包问题就是求解一个最优子集的问题,这里我们来讨论一个更简单的问题。对于任意一个集合来说,它都存在2^n个子集(一个集合所有的子集集合称为幂集)。
1)简单递归实现:
import java.util.ArrayList;
import java.util.List;public class Main {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);List<Integer> li = new ArrayList<>();f(0, list, li);}public static void f(int i, List list, List li) {if (i > (list.size() - 1)) {System.out.println(li);} else {li.add(list.get(i));// 左加f(i + 1, list, li);li.remove(list.get(i)); // 右去f(i + 1, list, li);}}}
二进制反射格雷码:这种算法得到的序列不仅是挤压序,而且还是一种最小变化法。下面的算法是使用了数学公式实现的,所以代码量很少,既然有数学公式,何乐而不为呢?难道要像NP问题一样没有公式才好吗?算法的“投机取巧”也在能直接利用数学公式上。
import java.util.Scanner;public class Main {public void getGrayCode(int bitNum){for(int i = 0; i < (int)Math.pow(2, bitNum); i++){int grayCode = (i >> 1) ^ i;System.out.println(numBinary(grayCode, bitNum));}}public String numBinary(int num, int bitNum){String ret = "";for(int i = bitNum-1; i >= 0; i--){ret += (num >> i) & 1;}return ret;}public static void main(String[] args) {Main test = new Main();Scanner in = new Scanner(System.in);int n = in.nextInt();test.getGrayCode(n);}
}