统计和生成所有不同的二叉树
给定一个整数N,如果N<1,代表空树,否则代表中序遍历结果为{1, 2, 3… N}。请返回可能的二叉树结构有多少。
统计所有不同的二叉树
如果中序遍历有序且无重复值,则二叉树必为搜索二叉树。
采用动态规划计算。data[i]代表i个节点的搜索二叉树有多少种可能。又包括以1为头节点,以2为头节点,…,一直到以N为头节点。
以i为头节点时,等于左子树的种数,乘以右子树的种数。data[i] = data[i-1]* data[N-i]。
Rust fn num_trees ( n : i32 ) -> i32 {
if n < 2 {
return 1 ;
}
let mut data = vec! [ 0 ; ( n + 1 ) as usize ];
data [ 0 ] = 1 ;
for i in 1 ..= n {
for j in 1 ..= i {
data [ i as usize ] += data [( j - 1 ) as usize ] * data [( i - j ) as usize ];
}
}
return data [ n as usize ];
}
进阶 生成所有不同的二叉树
N的含义不变,假设可能的二叉树有M种,请返回M个二叉树头节点,每个代表一种结构。
rust实现
Rust #[derive(Clone)]
pub struct Node {
pub val : i32 ,
pub left : Option < Box < Node >> ,
pub right : Option < Box < Node >> ,
}
impl Node {
pub fn new ( val : i32 ) -> Self {
Node {
val ,
left : None ,
right : None ,
}
}
}
pub fn generate_trees ( n : i32 ) -> Vec < Option < Box < Node >>> {
generate ( 1 , n )
}
fn generate ( start : i32 , end : i32 ) -> Vec < Option < Box < Node >>> {
let mut res = Vec :: new ();
if start > end {
res . push ( None );
return res ;
}
for i in start ..= end {
let head = Node :: new ( i );
let left_trees = generate ( start , i - 1 );
let right_trees = generate ( i + 1 , end );
for left in & left_trees {
for right in & right_trees {
let mut new_head = head . clone ();
new_head . left = left . clone ();
new_head . right = right . clone ();
res . push ( Some ( Box :: new ( new_head )));
}
}
}
res
}
#[cfg(test)]
mod tests {
use crate ::{ generate_trees , num_trees };
#[test]
fn it_works () {
let res = num_trees ( 2 );
assert_eq! ( res , 2 );
}
#[test]
fn it_works_2 () {
let num = 4 ;
let res = generate_trees ( num );
assert_eq! ( res . len (), num_trees ( num ) as usize );
}
}
#### java版本
``` java
public List < Node > generateTrees ( int n ) {
return generate ( 1 , n );
}
private List < Node > generate ( int start , int end ) {
List < Node > res = new ArrayList <> ();
if ( start > end ) {
res . add ( null );
}
Node head = null ;
for ( int i = start ; i <= end ; i ++ ) {
head = new Node ( i );
List < Node > left = generate ( start , i - 1 );
List < Node > right = generate ( i + 1 , end );
for ( Node l : left ) {
for ( Node r : right ) {
head . left = l ;
head . right = r ;
res . add ( cloneTree ( head ));
}
}
}
return res ;
}
public Node cloneTree ( Node root ) {
if ( root == null ) return null ;
Node node = new Node ( root . val );
node . left = cloneTree ( root . left );
node . right = cloneTree ( root . right );
return node ;
}
Box clone
在堆上重新分配一块区域,用不同的指针指向分配的新区域。因此,有两个保存一样数据,但是内存区域不同。
Rust fn main () {
let x = Box :: new ( 5 );
let y = x . clone ();
// 获取指针地址
let x_ptr = Box :: into_raw ( x ); // 获取 x 的原始指针并消耗 Box
let y_ptr = Box :: into_raw ( y ); // 获取 y 的原始指针并消耗 Box
// 使用 assert 判断地址是否相等
assert! ( ! std :: ptr :: eq ( x_ptr , y_ptr ), "x 和 y 的地址应该不相等" );
// 打印指针地址
println! ( "Address of x: {:p}" , x_ptr );
println! ( "Address of y: {:p}" , y_ptr );
println! ( "Address of z: {:p}" , y_ptr );
// 记得在使用完原始指针后释放内存
unsafe {
let _ = Box :: from_raw ( x_ptr );
let _ = Box :: from_raw ( y_ptr );
}
// Address of x: 0x55e91ead3b80
// Address of y: 0x55e91ead3ba0
}