1.給表達式加括弧(設計優先級)
給定一個含有數字和運算符的字符串,爲表達式添加括號,改變其運算優先級以求出不同的結果。你需要給出所有可能的組合的結果。有效的運算符號包含 +, - 以及 * 。
示例 1:
輸入: "2-1-1"
輸出: [0, 2]
解釋:
((2-1)-1) = 0
(2-(1-1)) = 2
示例 2:
輸入: "2*3-4*5"
輸出: [-34, -14, -10, -10, 10]
解釋:
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
解題思想:遇到運算符將表達式分爲兩部分,即運算符(+ - *)左邊部分和右邊部分,每部分的計算結果存儲於List中,根據運算符(+-*)循環計算當前表達式最終結果。 對於存儲於List中左右兩部分的計算結果遞歸進行運算。
以 2 * 3 - 4 * 5 爲例。
2 和 3 - 4 * 5 兩部分,中間是 * 號相連。
2 * 3 和 4 * 5 兩部分,中間是 - 號相連。
2 * 3 - 4 和 5 兩部分,中間是 * 號相連。
有了兩部分的結果,然後再通過中間的符號兩兩計算加入到最終的結果中即可。
比如第一種情況,2 和 3 - 4 * 5 兩部分,中間是 * 號相連。
2 的解就是 [2],3 - 4 * 5 的解就是 [-5, -17]。
把兩部分解通過 * 號計算,最終結果就是 [-10, -34]。
另外兩種情況也類似。
然後還需要遞歸出口。
如果給定的字符串只有數字,沒有運算符,那結果就是給定的字符串轉爲數字。
比如上邊的第一種情況,2 的解就是 [2]。
JAVA代碼如下:
class Solution {
//解決思路:遞歸解法
// 遇到運算符將表達式分爲兩部分,即運算符(+ - *)左邊部分和右邊部分,對於每部分的結果再遞歸進行運算,每部分的計算結果存儲與List中
public List<Integer> diffWaysToCompute(String input) {
List<Integer> ways = new ArrayList<>();
int len=input.length();
for(int i=0;i<len;i++){
char ch=input.charAt(i);
//如果當前字符是運算符,則將表達式分爲兩部分分別計算表達式左邊的結果和右邊的結果
if(ch=='+'||ch=='-'||ch=='*'){
List<Integer> left=diffWaysToCompute(input.substring(0,i));//subString()函數[0,i)左閉右開
List<Integer> right=diffWaysToCompute(input.substring(i+1));//從i+1到最後
for(int l:left){
for(int r:right){
if(ch=='+'){
ways.add(l+r);
}else if(ch=='-'){
ways.add(l-r);
}else{
ways.add(l*r);
}
}
}
}
}
//當傳入的input表達式中沒有運算符,
if(ways.size()==0)
ways.add(Integer.valueOf(input));
return ways;
}
}
2.構建不同的二叉搜索樹
給定一個整數 n,生成所有由 1 ... n 爲節點所組成的 二叉搜索樹 。
示例:
輸入:3
輸出:
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]
解釋:
以上的輸出對應以下 5 種不同結構的二叉搜索樹:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
提示:
0 <= n <= 8
解題思想:根據二叉搜索樹的性質,根的左樹所有的節點的value值小於根的value值,根的右子樹所有節點的value值大於根的value值。根據傳入的參數n,依次遍歷n作爲root,小於n的部分作爲左子樹節點遞歸構建左子樹,大於n的部分做爲右子樹節點遞歸構建右子樹,構建的左右子樹均保存在List<TreeNode>中,最後根據構建的不同左右子樹進行拼接。
JAVA代碼:
import java.util.ArrayList;
import java.util.List;
/**
* Created by 高先森 on 2020/7/1.
*/
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 class leetcode_95_biSearchTree {
public static void main(String[] args){
System.out.println(generateTrees(3));
}
public static List<TreeNode> generateTrees(int n) {
if(n<=0)
return new ArrayList<TreeNode>();
else
return createTree(1,n);
}
public static List<TreeNode> createTree(int begin,int end) {
List<TreeNode> resList=new ArrayList();
//1.遞歸出口正確的處理
if(begin>end) {
resList.add(null);
return resList;
}
// 錯誤處理
// if(begin>end)
// return new ArrayList<>();//返回一個空的ArrayList,無法提取空子樹(null)
//2.構建二叉搜索樹
for(int i=begin;i<=end;i++){
//2.1.建立根節點
TreeNode root;//此處如果直接是TreeNode root=new TreeNode(i);則每次修改左右子樹都是在同一個根上做變動,添加後面的樹,之前保存的樹也會變動
//2.2.遞歸構建左右子樹
for(TreeNode treeNode_left:createTree(begin,i-1)){
for(TreeNode treeNode_right:createTree(i+1,end)){
root=new TreeNode(i);//必須每次新開闢一個根節點
root.left=treeNode_left;//構建左子樹
root.right=treeNode_right;//構建右子樹
resList.add(root);
}
}
}
return resList;
}
}