LeetCode 熱題 HOT 100 Java題解——96. 不同的二叉搜尋樹
LeetCode 熱題 HOT 100 Java題解
96. 不同的二叉搜尋樹
題目:
給定一個整數 n n n,求以 1... n 1 ... n 1...n 為節點組成的二叉搜尋樹有多少種?
示例:
輸入: 3
輸出: 5
解釋:
給定 n = 3, 一共有 5 種不同結構的二叉搜尋樹:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
遞迴子問題
假設 n n n 個節點存在二叉排序樹的個數是 G ( n ) G (n) G(n),令 f ( i ) f(i) f(i) 為以 i i i 為根的二叉搜尋樹的個數,則
G ( n ) = f ( 1 ) + f ( 2 ) + f ( 3 ) + f ( 4 ) + . . . + f ( n ) G(n)=f(1)+f(2)+f(3)+f(4)+...+f(n) G(n)=f(1)+f(2)+f(3)+f(4)+...+f(n),
f ( i ) = G ( i − 1 ) ∗ G ( n − i ) f(i)=G(i−1)∗G(n−i) f(i)=G(i−1)∗G(n−i)
遞迴輕易寫出,2560ms,有時會超時
class Solution {
public int numTrees(int n) {
if (n == 0 || n == 1) return 1;
int res = 0;
for (int i = 1; i <= n; i++) {
res += numTrees(i - 1) * numTrees(n - i);
}
return res;
}
}
複雜度分析
-
時間複雜度: O ( ? ) O(?) O(?)
卡特蘭數複雜度。
-
空間複雜度: O ( ? ) O(?) O(?)
卡特蘭數複雜度。
記憶化遞迴
上述程式碼最大的問題就是太多重複計算,因此可以使用記憶化遞迴。
class Solution {
int[] mem;
public int recur(int n) {
if (mem[n] != 0) return mem[n];
int res = 0;
for (int i = 0; i < n; i++) {
res += recur(i) * recur(n - i - 1);
}
mem[n] = res;
return res;
}
public int numTrees(int n) {
if (n == 0 || n == 1) return 1;
mem = new int[n + 1];
mem[0] = mem[1] = 1;
return recur(n);
}
}
複雜度分析
-
時間複雜度: O ( n 2 ) O(n^2) O(n2)
與動態規劃複雜度相同。
-
空間複雜度: O ( n ) O(n) O(n)
需要 O ( n ) O(n) O(n)額外陣列空間。
動態規劃
從 d p [ 0 ] , d p [ 1 ] dp[0],dp[1] dp[0],dp[1]開始逐漸向後擴大。
public class Solution {
public int numTrees(int n) {
int[] dp = new int[n + 1];
dp[0] = dp[1] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= i; j++) {
dp[i] += dp[j - 1] * dp[i - j];
}
}
return dp[n];
}
}
複雜度分析
-
時間複雜度: O ( n 2 ) O(n^2) O(n2)
雙重迴圈。
-
空間複雜度: O ( n ) O(n) O(n)
需要 O ( n ) O(n) O(n)額外陣列空間。
數學方法——卡特蘭數
其實本體實質為計算卡塔蘭數 C n C_n Cn。卡塔蘭數更便於計算的定義如下:
C 0 = 1 , C n + 1 = 2 ( 2 n + 1 ) n + 2 C n C_0 = 1, \qquad C_{n+1} = \frac{2(2n+1)}{n+2}C_n C0=1,Cn+1=n+22(2n+1)Cn
public class Solution {
public int numTrees(int n) {
long C = 1;
for (int i = 0; i < n; ++i) {
C = C * 2 * (2 * i + 1) / (i + 2);
}
return (int) C;
}
}
複雜度分析
-
時間複雜度: O ( n ) O(n) O(n)
一重迴圈。
-
空間複雜度: O ( 1 ) O(1) O(1)
常數級別額外空間。
相關文章
- LeetCode 熱題 HOT 100 Java題解——33. 搜尋旋轉排序陣列LeetCodeJava排序陣列
- 96. 不同的二叉搜尋樹
- LeetCode 熱題 HOT 100 Java題解——94. 二叉樹的中序遍歷LeetCodeJava二叉樹
- LeetCode-096-不同的二叉搜尋樹LeetCode
- [leetCode]95. 不同的二叉搜尋樹 IILeetCode
- LeetCode-095-不同的二叉搜尋樹 IILeetCode
- LeetCode HOT 100:驗證二叉搜尋樹(從左右子樹獲取資訊進行推導)LeetCode
- 09/05 ? LeetCode 熱題 HOT 100 -- 22, 23,31LeetCode
- <動態規劃>Leetcode96.不同的二叉搜尋樹動態規劃LeetCode
- LeetCode hot100-二叉樹篇思路總結LeetCode二叉樹
- 【LeetCode動態規劃#04】不同的二叉搜尋樹(找規律,有點像智力題)LeetCode動態規劃
- Leetcode刷題筆記 501. 二叉搜尋樹中的眾數LeetCode筆記
- Day 36 | 62.不同路徑 、 63. 不同路徑 II 、343. 整數拆分、96.不同的二叉搜尋樹
- [Python手撕]不同的二叉搜尋樹Python
- Leetcode 700. 二叉搜尋樹中的搜尋(DAY 2)LeetCode
- leetcode 700. 二叉搜尋樹中的搜尋 思考分析LeetCode
- 【leetcode 簡單】 第六十八題 二叉搜尋樹的最近公共祖先LeetCode
- Leetcode 演算法題解系列 - 二維陣列快速查詢元素(二叉搜尋樹)LeetCode演算法陣列
- LeetCode 95 | 構造出所有二叉搜尋樹LeetCode
- LeetCode98. 驗證二叉搜尋樹LeetCode
- LeetCode-098-驗證二叉搜尋樹LeetCode
- LeetCode-099-恢復二叉搜尋樹LeetCode
- 【LeetCode】98. 驗證二叉搜尋樹LeetCode
- LeetCode-173-二叉搜尋樹迭代器LeetCode
- (40/60)整數拆分、不同的二叉搜尋樹
- LeetCode將有序陣列轉化為二叉搜尋樹--JavaLeetCode陣列Java
- [LeetCode題解]79. 單詞搜尋LeetCode
- leetcode 235. 二叉搜尋樹的最近公共祖先LeetCode
- 程式碼隨想錄演算法訓練營第十七天|leetcode654. 最大二叉樹、leetcode617.合併二叉樹、leetcode700.二叉搜尋樹中的搜尋、leetcode98.驗證二叉搜尋樹演算法LeetCode二叉樹
- leetcode-1382. 將二叉搜尋樹變平衡LeetCode
- 【ALGO】Leetcode 98.驗證二叉搜尋樹GoLeetCode
- dfs 驗證搜尋二叉樹——leetcode98二叉樹LeetCode
- 二叉搜尋樹
- (117)235. 二叉搜尋樹的最近公共祖先(leetcode)LeetCode
- leetcode 108.將有序陣列轉換為二叉搜尋樹 JavaLeetCode陣列Java
- LeetCode-230-二叉搜尋樹中第K小的元素LeetCode
- Leetcode230. 二叉搜尋樹中第K小的元素LeetCode
- Leetcode 938. 二叉搜尋樹的範圍和(DAY 2)LeetCode