生活随笔
收集整理的這篇文章主要介紹了
数据结构与算法--求1~n能组成的所有二叉搜索树的排列
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
給定一個整數n,生成并返回所有N個節點組成并且節點值從1到n互不相同的不同二叉樹,可以按照任意順序
數據結構與算法–面試必問AVL樹原理及實現
數據結構與算法–二叉樹的深度問題
數據結構與算法–二叉堆(最大堆,最小堆)實現及原理
數據結構與算法–二叉查找樹轉順序排列雙向鏈表
數據結構與算法-- 二叉樹中和為某一值的路徑
數據結構與算法-- 二叉樹后續遍歷序列校驗
數據結構與算法-- 廣度優先打印二叉樹
數據結構與算法–解決問題的方法- 二叉樹的的鏡像
數據結構與算法–重建二叉樹
數據結構與算法–二叉查找樹實現原理
數據結構與算法–二叉樹實現原理
數據結構與算法–B樹原理及實現
數據結構與算法–數字在排序數組中出現次數
數據結構與算法–死磕二叉樹
數據結構與算法–二叉樹第k個大的節點
數據結構與算法–求1~n能組成的所有二叉搜索樹的排列
全排列問題
-
排列組合的問題在之前的文中我們已經求解過:
數據結構與算法–字符串的排列組合問題
數據結構與算法–代碼完整性案例分析
-
在求數組全排列的過程中,我們將數組的每一位看成是獨立的,接著每一位上分別排列1~9 的每一位樹,一次對數組的n為進行遞歸,得到我們的全排列。
-
現題中需要讓1~n 組成n 個階段的不同二叉樹,也就是我們需要求解二叉樹的全排列
方法一:轉為數組全排列實現
public class BuildGenerateTrees {public static void main(String[] args
) {List<BinaryNode> binaryNodes
= new ArrayList<>();List<String> middleSearch
= new ArrayList<>();binaryNodes
= generateTrees(4);for (int i
= 0; i
< binaryNodes
.size(); i
++) {StringBuilder strBu
= new StringBuilder();middleSearch
.add(printTree(binaryNodes
.get(i
),strBu
));}middleSearch
.forEach(System.out
::println);}public static List<BinaryNode> generateTrees(int n
){List<BinaryNode> binaryNodes
= new ArrayList<>();List<String> middleSearchStr
= new ArrayList<>();int[] array
= new int[n
];for (int i
= 1; i
<= n
; i
++) {array
[i
-1] = i
;}return buildGenerateTree(array
, binaryNodes
, 0, middleSearchStr
);}public static List<BinaryNode> buildGenerateTree(int[] array
, List<BinaryNode> binaryNodes
, int start
, List<String> middleSearchStr
){if(array
== null || array
.length
<=1 || start
== (array
.length
-1)){BinaryNode newNode
= buildBinarySearchTree(array
);StringBuilder str
= new StringBuilder();String middleStr
= printTree(newNode
, str
);if(!middleSearchStr
.contains(middleStr
)){middleSearchStr
.add(middleStr
);binaryNodes
.add(newNode
);}}for (int i
= start
; i
< array
.length
; i
++) {int temp
= array
[i
];array
[i
] = array
[start
];array
[start
] = temp
;buildGenerateTree(array
, binaryNodes
, start
+1, middleSearchStr
);temp
= array
[i
];array
[i
] = array
[start
];array
[start
] = temp
;}return binaryNodes
;}public static String printTree(BinaryNode t
, StringBuilder strbu
) {if (t
== null || t
.getElement() == null) {return strbu
.toString();}for (int i
= 0; i
< t
.getCount(); i
++) {strbu
.append(t
.getElement() + ":" + t
.getHeight()+" ");}printTree(t
.getLeft(), strbu
);printTree(t
.getRight(), strbu
);return strbu
.toString();}public static BinaryNode buildBinarySearchTree(int[] array
){if(array
== null || array
.length
<= 0){return null;}BinaryNode node
= new BinaryNode(null, null, null);for (int i
= 0; i
< array
.length
; i
++) {node
= insertNode(node
, array
[i
]);}return node
;}public static BinaryNode insertNode(BinaryNode node
, Integer k
){if(k
== null){return node
;}if(node
== null || node
.getElement() == null){node
= new BinaryNode(k
, null, null);}int validateK
= node
.compareTo(k
);if(validateK
> 0){node
.setLeft(insertNode(node
.getLeft(), k
));}else if (validateK
< 0){node
.setRight(insertNode(node
.getRight(), k
));}return node
;}
}
- 如上實現方案時間復雜度在O(n2), 空間復雜度存在兩部分,一部分二叉搜索樹數組,這部分取決于節點數量,數量不同排列的個數不同,另一部分在于存儲二叉排序樹的前序遍歷字符串,因此空間復雜度也不會小。
方法二:分治法
- 方案一的時間復雜度,空間復雜度都不是太理想,第一想法實現方案往往題目沒有這么簡單,在方法一中我們實現我們是受到之前文章中思路的影響,將之前的排列組合的思路套用在 二叉搜索樹的排列上,但是因為兩種數據結構本身復雜度就相差很大,導致二叉搜索樹的排列問題異常復雜。
- 我們換一種思路,這個也是看到別的思路,看到后就茅塞頓開,因為一旦思路被固定住,要想跳出來還是比較困難的,就和寫小說的作者肯定不會去看別人寫的小說是一個道理。
- 我們直接將數組全排列思想用到二叉樹搜索樹中:
- 在1~n中每個數字都有可能是根節點,確定根節點后 k,k 之前的數據 1 ~ k就是左子樹,在k ~ n中每一個就是右子樹
- 那么我們遍歷1 ~ n中每一位,讓每個數都構造成不同根的 一棵二叉搜索樹
- 接著處理左子樹 1 ~ k,同樣,1~k中的左子樹也是一棵二叉搜索樹,依然套用以上邏輯,右子樹同理。分別記錄為leftList, rightLIst
- 那么構造完左右子樹后,我們只需要在左子樹 leftList,rightList進行組合(雙循環構造每種排列方式),就得到了整個二叉樹的排列
-如下圖,列舉其中一種情況:
public class BuildGenerateTrees {public static void main(String[] args
) {List<BinaryNode> binaryNodes
= generateTreesBinary(1, 4);BinarySearchTree binarySearchTree
= new BinarySearchTree();for (BinaryNode binaryNode
: binaryNodes
) {binarySearchTree
.printTree(binaryNode
);}}public static List<BinaryNode>generateTreesBinary(int start
, int end
){List<BinaryNode> binaryNodes
= new LinkedList<>();if(start
> end
){binaryNodes
.add(null);return binaryNodes
;}for (int i
=start
;i
<=end
;i
++){List<BinaryNode> leftNode
= generateTreesBinary(start
, i
-1);List<BinaryNode> rightNode
= generateTreesBinary(i
+1, end
);for (BinaryNode left
: leftNode
) {for (BinaryNode right
: rightNode
) {binaryNodes
.add(new BinaryNode(i
, left
, right
));}}}return binaryNodes
;}
}
- 以上思路理解起來更清晰,代碼實現方式也更簡單,時間復雜度還是取決于n的大小,假設n個階段能構建Cn棵二叉搜索樹,那么時間復雜度一棵樹生成需要O(n),Cn棵樹O(n*Cn)
- 空間復雜度,每一棵樹都有n個階段,有Cn棵樹,總空間復雜度O(n*Cn)
上一篇:數據結構與算法–二叉樹第k個大的節點
下一篇:數據結構與算法一篇幫助你吃下KMP算法
總結
以上是生活随笔為你收集整理的数据结构与算法--求1~n能组成的所有二叉搜索树的排列的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。