use std::cell::RefCell;
use std::cmp::{max, Ordering};
use std::collections::VecDeque;
use std::fmt::{Display, Formatter, Write};
use std::rc::Rc;
use super::raw_def::TreeNode;
use super::shortcuts::{new_cell, new_node, new_rc, to_ptr, val as pointed};
pub type TreeHandle = Option<Rc<RefCell<TreeNode>>>;
#[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Clone)]
pub enum TraversalType {
PreOrder,
InOrder,
PostOrder,
LevelOrder,
}
#[derive(Debug, Eq, PartialEq)]
pub enum TreeError {
Nondeterministic(TraversalType, TraversalType),
LeetcodeFormatError,
}
impl Display for TreeError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Nondeterministic(t1, t2) => f.write_fmt(format_args!(
"tree structure cannot be determined by `{:?}` and `{:?}`",
t1, t2
)),
Self::LeetcodeFormatError => f.write_str("leetcode format error"),
}
}
}
pub struct TreeBuilder;
impl TreeBuilder {
pub fn from_leetcode(values: &[Option<i32>]) -> TreeHandle {
if values.is_empty() {
return None;
}
let root = new_node(unsafe { (*values.get_unchecked(0)).unwrap() });
let mut q: VecDeque<Rc<RefCell<TreeNode>>> = VecDeque::with_capacity(4); q.push_back(Rc::clone(root.as_ref().unwrap()));
for arr in values[1..].chunks(2) {
let cur_head = q.pop_front().unwrap();
unsafe {
if let Some(left_child_val) = *arr.get_unchecked(0) {
let core = new_rc(left_child_val);
q.push_back(Rc::clone(&core));
(*cur_head.as_ptr()).left = Some(core);
}
if arr.len() == 2 {
if let Some(right_child_val) = *arr.get_unchecked(1) {
let core = new_rc(right_child_val);
q.push_back(Rc::clone(&core));
(*cur_head.as_ptr()).right = Some(core);
}
}
}
}
root
}
pub fn from_leetcode_raw(s: &str) -> Result<TreeHandle, TreeError> {
if let [left_bracket, nums @ .., right_bracket] = s.as_bytes() {
if *left_bracket != b'[' || *right_bracket != b']' {
return Err(TreeError::LeetcodeFormatError);
}
if nums.is_empty() {
return Ok(None);
}
let mut v = Vec::with_capacity(4);
for n in unsafe { std::str::from_utf8_unchecked(nums) }.split(',') {
if n == "null" {
v.push(None);
} else {
match n.parse::<i32>() {
Ok(i) => v.push(Some(i)),
Err(_) => return Err(TreeError::LeetcodeFormatError),
}
}
}
v.shrink_to_fit();
Ok(Self::from_leetcode(&v))
} else {
Err(TreeError::LeetcodeFormatError)
}
}
pub fn from_twos(
seq1_type: TraversalType,
seq1: &[i32],
seq2_type: TraversalType,
seq2: &[i32],
) -> Result<TreeHandle, TreeError> {
use TraversalType::*;
match (seq1_type, seq2_type) {
(PreOrder, InOrder) => Ok(Self::from_pre_in(seq1, seq2)),
(InOrder, PreOrder) => Ok(Self::from_pre_in(seq2, seq1)),
(PostOrder, InOrder) => Ok(Self::from_post_in(seq1, seq2)),
(InOrder, PostOrder) => Ok(Self::from_post_in(seq2, seq1)),
(LevelOrder, InOrder) => Ok(Self::from_level_in(seq1, seq2)),
(InOrder, LevelOrder) => Ok(Self::from_level_in(seq2, seq1)),
(o1, o2) => Err(TreeError::Nondeterministic(o1, o2)),
}
}
#[inline]
pub fn from_pre_in(pre_order: &[i32], in_order: &[i32]) -> TreeHandle {
assert_eq!(pre_order.len(), in_order.len(), "invariance violated");
if pre_order.is_empty() {
return None;
}
let value = unsafe { *pre_order.get_unchecked(0) };
let pos = in_order
.iter()
.position(|&v| v == value)
.expect("invariance violated");
let ret = new_rc(unsafe { *in_order.get_unchecked(pos) });
ret.borrow_mut().left = Self::from_pre_in(&pre_order[1..=pos], &in_order[..pos]);
ret.borrow_mut().right = Self::from_pre_in(&pre_order[pos + 1..], &in_order[pos + 1..]);
Some(ret)
}
pub fn from_post_in(post_order: &[i32], in_order: &[i32]) -> TreeHandle {
assert_eq!(post_order.len(), in_order.len(), "invariance violated");
if let Some((&value, post_order)) = post_order.split_last() {
let pos = in_order
.iter()
.position(|&v| v == value)
.expect("invariance violated");
let ret = new_rc(unsafe { *in_order.get_unchecked(pos) });
ret.borrow_mut().left = Self::from_post_in(&post_order[..pos], &in_order[..pos]);
ret.borrow_mut().right = Self::from_post_in(&post_order[pos..], &in_order[pos + 1..]);
Some(ret)
} else {
None
}
}
#[inline]
pub fn from_level_in(level_order: &[i32], in_order: &[i32]) -> TreeHandle {
assert_eq!(level_order.len(), in_order.len(), "invariance violated");
pub fn from_level_in_inner(level_order: &[i32], in_order: &[i32]) -> TreeHandle {
if in_order.is_empty() {
return None;
}
let (level_index, pos, value) = 'outer: loop {
for (level_index, &level_value) in level_order.iter().enumerate() {
for (in_index, &in_value) in in_order.iter().enumerate() {
if level_value == in_value {
break 'outer (level_index, in_index, level_value);
}
}
}
panic!("invariance violated!");
};
let cell = new_cell(value);
cell.borrow_mut().left =
from_level_in_inner(&level_order[level_index + 1..], &in_order[..pos]);
cell.borrow_mut().right =
from_level_in_inner(&level_order[level_index + 1..], &in_order[pos + 1..]);
Some(Rc::new(cell))
}
from_level_in_inner(level_order, in_order)
}
}
#[derive(Debug, Clone)]
pub struct T(pub TreeHandle);
impl T {
#[inline]
pub fn height(&self) -> usize {
unsafe { Self::height_maybe_null(to_ptr(self.0.as_ref())) }
}
#[inline]
unsafe fn height_maybe_null(root: *const TreeNode) -> usize {
if root.is_null() {
0
} else {
Self::height_nonnull(root)
}
}
unsafe fn height_nonnull(root: *const TreeNode) -> usize {
let mut stk = Vec::with_capacity(4);
stk.set_len(1);
*stk.get_unchecked_mut(0) = (root, 1);
let mut max_height = 1_usize;
while !stk.is_empty() {
let (cur_node, h) = stk.pop().unwrap();
max_height = max(max_height, h);
if let Some(rc) = &(*cur_node).right {
stk.push((rc.as_ptr(), h + 1));
}
if let Some(rc) = &(*cur_node).left {
stk.push((rc.as_ptr(), h + 1));
}
}
max_height
}
pub fn pre_order(&self) -> Vec<i32> {
if let Some(ref rc) = self.0 {
let mut v = Vec::with_capacity(4);
let mut ret = Vec::with_capacity(4);
unsafe {
v.set_len(1);
*v.get_unchecked_mut(0) = rc.as_ptr() as *const TreeNode;
}
while !v.is_empty() {
let top = v.pop().unwrap();
ret.push(pointed(top));
if let Some(rc) = unsafe { &(*top).right } {
v.push(rc.as_ptr());
}
if let Some(rc) = unsafe { &(*top).left } {
v.push(rc.as_ptr());
}
}
ret.shrink_to_fit();
ret
} else {
Default::default()
}
}
#[inline]
pub fn in_order(&self) -> Vec<i32> {
fn in_order_inner(root: *const TreeNode, v: &mut Vec<i32>) {
if let Some(rc) = unsafe { &(*root).left } {
in_order_inner(rc.as_ptr(), v);
}
v.push(pointed(root));
if let Some(rc) = unsafe { &(*root).right } {
in_order_inner(rc.as_ptr(), v);
}
}
if let Some(ref rc) = self.0 {
let mut v = Vec::with_capacity(4);
in_order_inner(rc.as_ptr(), &mut v);
v.shrink_to_fit();
v
} else {
Default::default()
}
}
pub fn post_order(&self) -> Vec<i32> {
fn post_order_inner(root: *const TreeNode, v: &mut Vec<i32>) {
if let Some(rc) = unsafe { &(*root).left } {
post_order_inner(rc.as_ptr(), v);
}
if let Some(rc) = unsafe { &(*root).right } {
post_order_inner(rc.as_ptr(), v);
}
v.push(pointed(root));
}
if let Some(ref rc) = self.0 {
let mut v = Vec::with_capacity(4);
post_order_inner(rc.as_ptr(), &mut v);
v.shrink_to_fit();
v
} else {
Default::default()
}
}
pub fn level_order(&self) -> Vec<i32> {
if let Some(ref rc) = self.0 {
let mut q = VecDeque::with_capacity(4);
q.push_back(rc.as_ptr() as *const TreeNode);
let mut v = Vec::with_capacity(4);
while !q.is_empty() {
let top = q.pop_front().unwrap();
v.push(pointed(top));
if let Some(rc) = unsafe { &(*top).left } {
q.push_back(rc.as_ptr());
}
if let Some(rc) = unsafe { &(*top).right } {
q.push_back(rc.as_ptr());
}
}
v.shrink_to_fit();
v
} else {
Default::default()
}
}
#[inline]
pub fn re_owned(&mut self) {
self.0 = self.detach().0;
}
pub fn detach(&self) -> Self {
let v1 = self.pre_order();
let v2 = self.in_order();
Self(TreeBuilder::from_pre_in(&v1, &v2))
}
#[inline]
pub fn is_balanced(&self) -> bool {
fn is_balanced_inner(root: *const TreeNode) -> bool {
if !root.is_null() {
let left_ptr = to_ptr(unsafe { (*root).left.as_ref() });
let right_ptr = to_ptr(unsafe { (*root).right.as_ref() });
let mut h1 = unsafe { T::height_maybe_null(left_ptr) };
let mut h2 = unsafe { T::height_maybe_null(right_ptr) };
if h1 < h2 {
std::mem::swap(&mut h1, &mut h2);
}
h1 - h2 <= 1 && is_balanced_inner(left_ptr) && is_balanced_inner(right_ptr)
} else {
true
}
}
is_balanced_inner(to_ptr(self.0.as_ref()))
}
#[inline]
pub fn is_binary_search_tree(&self) -> bool {
self.in_order()
.windows(2)
.all(|tp| unsafe { tp.get_unchecked(0).cmp(tp.get_unchecked(1)) } == Ordering::Less)
}
pub fn to_leetcode_raw(&self) -> String {
let mut s = String::with_capacity(2);
unsafe {
let m = s.as_mut_vec();
m.set_len(1);
*m.get_unchecked_mut(0) = b'[';
}
debug_assert_eq!(s, "[");
for o in self.to_leetcode() {
if let Some(i) = o {
s.write_fmt(format_args!("{},", i))
.expect("String::write_fmt() failed");
} else {
s.write_str("null,").expect("String::write_fmt() failed");
}
}
let pos = s.as_bytes().len() - 1;
unsafe {
*s.as_mut_vec().get_unchecked_mut(pos) = b']';
}
s.shrink_to_fit();
s
}
pub fn to_leetcode(&self) -> Vec<Option<i32>> {
if let Some(ref rc) = self.0 {
let root = rc.as_ptr() as *const TreeNode;
let mut ans = Vec::with_capacity(4);
let mut q = VecDeque::with_capacity(4);
q.push_back(root);
while !q.is_empty() {
let top = q.pop_front().unwrap();
if top.is_null() {
ans.push(None);
} else {
ans.push(Some(pointed(top)));
q.push_back(to_ptr(unsafe { (*top).left.as_ref() }));
q.push_back(to_ptr(unsafe { (*top).right.as_ref() }));
}
}
ans.truncate(ans.iter().rev().skip_while(|o| o.is_none()).count());
ans
} else {
Default::default()
}
}
pub fn len(&self) -> usize {
if let Some(ref rc) = self.0 {
let mut v = Vec::with_capacity(4);
let mut ret = 0_usize;
unsafe {
v.set_len(1);
*v.get_unchecked_mut(0) = rc.as_ptr() as *const TreeNode;
}
while !v.is_empty() {
let top = v.pop().unwrap();
ret += 1;
if let Some(rc) = unsafe { &(*top).right } {
v.push(rc.as_ptr());
}
if let Some(rc) = unsafe { &(*top).left } {
v.push(rc.as_ptr());
}
}
ret
} else {
0
}
}
}
impl Display for T {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.to_leetcode_raw())
}
}
impl PartialEq for T {
fn eq(&self, other: &Self) -> bool {
self.pre_order().eq(&other.pre_order()) && self.in_order().eq(&other.in_order())
}
}
#[macro_export]
macro_rules! btree {
() => { None };
($($val: expr),+ $(,)?) => {
{
let values = vec![$(stringify!($val)),+].iter()
.map(|v|v.parse::<i32>().ok())
.collect::<Vec<Option<i32>>>();
leetcode_test_utils::tree::TreeBuilder::from_leetcode(values.as_slice())
}
};
}
#[macro_export]
macro_rules! new_left {
($rc: expr, $val: expr) => {
$rc.borrow_mut().left = leetcode_test_utils::tree::shortcuts::new_node($val);
};
}
#[macro_export]
macro_rules! new_right {
($rc: expr, $val: expr) => {
$rc.borrow_mut().right = leetcode_test_utils::tree::shortcuts::new_node($val);
};
}
#[macro_export]
macro_rules! new_child {
($rc:expr, left, $val:expr) => {
leetcode_test_utils::new_left!($rc, $val);
};
($rc:expr, l, $val:expr) => {
leetcode_test_utils::new_left!($rc, $val);
};
($rc:expr, L, $val:expr) => {
leetcode_test_utils::new_left!($rc, $val);
};
($rc:expr, right, $val:expr) => {
leetcode_test_utils::new_right!($rc, $val);
};
($rc:expr, r, $val:expr) => {
leetcode_test_utils::new_right!($rc, $val);
};
($rc:expr, R, $val:expr) => {
leetcode_test_utils::new_right!($rc, $val);
};
($rc:expr, [$left:expr, $right:expr]) => {
leetcode_test_utils::new_left!($rc, $left);
leetcode_test_utils::new_right!($rc, $right);
};
}