求集合 [1, 2] 的所有子集,即求出 [], [1], [2], [1, 2](通常 [] 空集合也被看作为子集之一)。观察图 1,可看到从根节点开始,每个叶子节点都有两个子节点:代表该节点是否选择加入下一个数字。
图 2
图 1
以下代码是使用递归的示例:
recursive(Integer[] input, Integer index, LinkedList<Integer> subset, List<List<Indeger>> result)>>)
subset 即子集的初始值是 [],此时 index = 0:
当 index = 0 时面临两种选择:是否加入 1;
当 index = 1 也面临两种选择,是否加入 2;
// 不选择当前数字 input[index]
recursive(input, index + 1, subset, result)
// 选择当前数字 input[index] **并继续下一步的选择**。
subset.add(input[index])
recursive(input, index + 1, subset, result)
在 index = 2 满足边界条件时开始执行递归出栈:
首先出栈的是 index = 2(满足边界条件),停止递归并返回 [];
然后出栈 index = 1,返回 [];同时在这一步选择:
subset.add(input[1]) // 返回 [2]
此外,请留意上述步骤:当选择数字以后,subsets = [1],并继续往前:
recursive(input, index + 1, [1], result)
// index = 2 时,满足边界条件返回
因为 subsets 在栈结构中是一个引用对象,在返回到上一个任务时其是被修改状态,应当移除其最后一个元素:
subset.removeLast();
图 3