分冶法的思想及其应用系列
分冶法的思想
把复杂问题分成较小的与原问题类型相同的子问题,可以求解所有的子问题的解,可以将子问题的解合并成原复杂问题的解
1.原问题可以分解成若干个相同类型的子问题
2.(缩小到一定规模的)子问题可以容易解决
3.子问题的解可以合并成原问题的解
分冶法的应用
1.给表达式加括号(列出所有优先级下的表达式输出)
Input: “2-1-1”.
((2-1)-1) = 0
(2-(1-1)) = 2
Output : [0, 2]
(1).以运算符为划分,表达式字符串可以继续划分成类型相同的表达式字符串的子问题
(2).(当表达式字符串缩小成一定规模)子问题“1-1”可以求解
(3).以运算符划分可以成为两种情况的子问题,a. 以第一个减号运算符划分"2"和“1-1” ,b.以第二个减号运算符划分"2-1"和“1”,a和b的解合并的解正是问题添加括号(列出所有优先级情况)的所有解
public List<Integershi> diffWaysToCompute(String input) {
List<Integer> ways = new ArrayList<>();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c == '+' || c == '-' || c == '*') {
List<Integer> left = diffWaysToCompute(input.substring(0, i));
List<Integer> right = diffWaysToCompute(input.substring(i + 1));
for (int l : left) {
for (int r : right) {
switch (c) {
case '+':
ways.add(l + r);
break;
case '-':
ways.add(l - r);
break;
case '*':
ways.add(l * r);
break;
}
}
}
}
}
if (ways.size() == 0) {
ways.add(Integer.valueOf(input));
}
return ways;
}
2.给定一个数字 n,要求生成根节点分别为 1…n 的所有二叉搜索树。
(1).以小于等于n的任意数为划分,剩下的数可以继续划分成类型相同的子问题
(2).(当数组缩小成一定规模)子问题“1”可以求解
(3).以数划分可以成为三种情况的子问题,a. 以1划分为3和2 ,b.以2划分为1和3,c,以3划分为1和2. 以二叉树的特性(当前结点:左边的结点小于我,右边的结点大于我),所以b只有一种左1右3,a和c有两种情况的子问题,以a为例当先右3时2就在3下面的左边,先2时3就在2下面的右边,同理可以判断c. a,b,c的所有解合并的解正是问题给定数字 3,生成根节点分别为 1,2,3的所有二叉搜索树
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public List<TreeNode> generateTrees(int n) {
if (n < 1) {
return new LinkedList<TreeNode>();
}
return generateSubtrees(1, n);
}
private List<TreeNode> generateSubtrees(int s, int e) {
List<TreeNode> res = new LinkedList<TreeNode>();
if (s > e) {
res.add(null);
return res;
}
for (int i = s; i <= e; ++i) {
List<TreeNode> leftSubtrees = generateSubtrees(s, i - 1);
List<TreeNode> rightSubtrees = generateSubtrees(i + 1, e);
for (TreeNode left : leftSubtrees) {
for (TreeNode right : rightSubtrees) {
TreeNode root = new TreeNode(i);
root.left = left;
root.right = right;
res.add(root);
}
}
}
return res;
}