Skip to content

Commit

Permalink
feat: add solutions to lc problem: No.0108
Browse files Browse the repository at this point in the history
No.0108.Convert Sorted Array to Binary Search Tree
  • Loading branch information
yanglbme committed Dec 31, 2024
1 parent acbf443 commit 719049e
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,19 @@ tags:

### 方法一:二分 + 递归

我们设计一个递归函数 $dfs(l, r)$,表示当前待构造的二叉搜索树的节点值都在数组 `nums` 的下标范围 $[l, r]$ 内。该函数返回构造出的二叉搜索树的根节点。
我们设计一个递归函数 $\textit{dfs}(l, r)$,表示当前待构造的二叉搜索树的节点值都在数组 $\textit{nums}$ 的下标范围 $[l, r]$ 内。该函数返回构造出的二叉搜索树的根节点。

函数 $dfs(l, r)$ 的执行流程如下:
函数 $\textit{dfs}(l, r)$ 的执行流程如下:

1. 如果 $l > r$,说明当前数组为空,返回 `null`
2. 如果 $l \leq r$,取数组中下标为 $mid = \lfloor \frac{l + r}{2} \rfloor$ 的元素作为当前二叉搜索树的根节点,其中 $\lfloor x \rfloor$ 表示对 $x$ 向下取整。
3. 递归地构造当前二叉搜索树的左子树,其根节点的值为数组中下标为 $mid - 1$ 的元素,左子树的节点值都在数组的下标范围 $[l, mid - 1]$ 内。
4. 递归地构造当前二叉搜索树的右子树,其根节点的值为数组中下标为 $mid + 1$ 的元素,右子树的节点值都在数组的下标范围 $[mid + 1, r]$ 内。
2. 如果 $l \leq r$,取数组中下标为 $\textit{mid} = \lfloor \frac{l + r}{2} \rfloor$ 的元素作为当前二叉搜索树的根节点,其中 $\lfloor x \rfloor$ 表示对 $x$ 向下取整。
3. 递归地构造当前二叉搜索树的左子树,其根节点的值为数组中下标为 $\textit{mid} - 1$ 的元素,左子树的节点值都在数组的下标范围 $[l, \textit{mid} - 1]$ 内。
4. 递归地构造当前二叉搜索树的右子树,其根节点的值为数组中下标为 $\textit{mid} + 1$ 的元素,右子树的节点值都在数组的下标范围 $[\textit{mid} + 1, r]$ 内。
5. 返回当前二叉搜索树的根节点。

答案即为函数 $dfs(0, n - 1)$ 的返回值。
答案即为函数 $\textit{dfs}(0, n - 1)$ 的返回值。

时间复杂度 $O(n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 `nums` 的长度。
时间复杂度 $O(n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。

<!-- tabs:start -->

Expand All @@ -86,13 +86,11 @@ tags:
# self.right = right
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
def dfs(l, r):
def dfs(l: int, r: int) -> Optional[TreeNode]:
if l > r:
return None
mid = (l + r) >> 1
left = dfs(l, mid - 1)
right = dfs(mid + 1, r)
return TreeNode(nums[mid], left, right)
return TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r))

return dfs(0, len(nums) - 1)
```
Expand Down Expand Up @@ -128,9 +126,7 @@ class Solution {
return null;
}
int mid = (l + r) >> 1;
TreeNode left = dfs(l, mid - 1);
TreeNode right = dfs(mid + 1, r);
return new TreeNode(nums[mid], left, right);
return new TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r));
}
}
```
Expand All @@ -152,14 +148,12 @@ class Solution {
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
function<TreeNode*(int, int)> dfs = [&](int l, int r) -> TreeNode* {
auto dfs = [&](this auto&& dfs, int l, int r) -> TreeNode* {
if (l > r) {
return nullptr;
}
int mid = (l + r) >> 1;
auto left = dfs(l, mid - 1);
auto right = dfs(mid + 1, r);
return new TreeNode(nums[mid], left, right);
return new TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r));
};
return dfs(0, nums.size() - 1);
}
Expand All @@ -184,8 +178,7 @@ func sortedArrayToBST(nums []int) *TreeNode {
return nil
}
mid := (l + r) >> 1
left, right := dfs(l, mid-1), dfs(mid+1, r)
return &TreeNode{nums[mid], left, right}
return &TreeNode{nums[mid], dfs(l, mid-1), dfs(mid+1, r)}
}
return dfs(0, len(nums)-1)
}
Expand All @@ -209,16 +202,14 @@ func sortedArrayToBST(nums []int) *TreeNode {
*/

function sortedArrayToBST(nums: number[]): TreeNode | null {
const n = nums.length;
if (n === 0) {
return null;
}
const mid = n >> 1;
return new TreeNode(
nums[mid],
sortedArrayToBST(nums.slice(0, mid)),
sortedArrayToBST(nums.slice(mid + 1)),
);
const dfs = (l: number, r: number): TreeNode | null => {
if (l > r) {
return null;
}
const mid = (l + r) >> 1;
return new TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r));
};
return dfs(0, nums.length - 1);
}
```

Expand All @@ -243,23 +234,24 @@ function sortedArrayToBST(nums: number[]): TreeNode | null {
// }
// }
// }
use std::cell::RefCell;
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
fn to_bst(nums: &Vec<i32>, start: usize, end: usize) -> Option<Rc<RefCell<TreeNode>>> {
if start >= end {
return None;
}
let mid = start + (end - start) / 2;
Some(Rc::new(RefCell::new(TreeNode {
val: nums[mid],
left: Self::to_bst(nums, start, mid),
right: Self::to_bst(nums, mid + 1, end),
})))
}

pub fn sorted_array_to_bst(nums: Vec<i32>) -> Option<Rc<RefCell<TreeNode>>> {
Self::to_bst(&nums, 0, nums.len())
fn dfs(nums: &Vec<i32>, l: usize, r: usize) -> Option<Rc<RefCell<TreeNode>>> {
if l > r {
return None;
}
let mid = (l + r) / 2;
if mid >= nums.len() {
return None;
}
let mut node = Rc::new(RefCell::new(TreeNode::new(nums[mid])));
node.borrow_mut().left = dfs(nums, l, mid - 1);
node.borrow_mut().right = dfs(nums, mid + 1, r);
Some(node)
}
dfs(&nums, 0, nums.len() - 1)
}
}
```
Expand All @@ -285,14 +277,46 @@ var sortedArrayToBST = function (nums) {
return null;
}
const mid = (l + r) >> 1;
const left = dfs(l, mid - 1);
const right = dfs(mid + 1, r);
return new TreeNode(nums[mid], left, right);
return new TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r));
};
return dfs(0, nums.length - 1);
};
```

#### C#

```cs
/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
public class Solution {
private int[] nums;

public TreeNode SortedArrayToBST(int[] nums) {
this.nums = nums;
return dfs(0, nums.Length - 1);
}

private TreeNode dfs(int l, int r) {
if (l > r) {
return null;
}
int mid = (l + r) >> 1;
return new TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r));
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@ tags:

### Solution 1: Binary Search + Recursion

We design a recursive function $dfs(l, r)$, which indicates that the node values of the current binary search tree to be constructed are all within the index range $[l, r]$ of the array `nums`. This function returns the root node of the constructed binary search tree.
We design a recursive function $\textit{dfs}(l, r)$, which represents that the values of the nodes to be constructed in the current binary search tree are within the index range $[l, r]$ of the array $\textit{nums}$. This function returns the root node of the constructed binary search tree.

The execution process of the function $dfs(l, r)$ is as follows:
The execution process of the function $\textit{dfs}(l, r)$ is as follows:

1. If $l > r$, it means the current array is empty, return `null`.
2. If $l \leq r$, take the element with the index $mid = \lfloor \frac{l + r}{2} \rfloor$ in the array as the root node of the current binary search tree, where $\lfloor x \rfloor$ represents rounding down $x$.
3. Recursively construct the left subtree of the current binary search tree, whose root node value is the element with the index $mid - 1$ in the array, and the node values of the left subtree are all within the index range $[l, mid - 1]$ of the array.
4. Recursively construct the right subtree of the current binary search tree, whose root node value is the element with the index $mid + 1$ in the array, and the node values of the right subtree are all within the index range $[mid + 1, r]$ of the array.
1. If $l > r$, it means the current array is empty, so return `null`.
2. If $l \leq r$, take the element at index $\textit{mid} = \lfloor \frac{l + r}{2} \rfloor$ of the array as the root node of the current binary search tree, where $\lfloor x \rfloor$ denotes the floor function of $x$.
3. Recursively construct the left subtree of the current binary search tree, with the root node's value being the element at index $\textit{mid} - 1$ of the array. The values of the nodes in the left subtree are within the index range $[l, \textit{mid} - 1]$ of the array.
4. Recursively construct the right subtree of the current binary search tree, with the root node's value being the element at index $\textit{mid} + 1$ of the array. The values of the nodes in the right subtree are within the index range $[\textit{mid} + 1, r]$ of the array.
5. Return the root node of the current binary search tree.

The answer is the return value of the function $dfs(0, n - 1)$.
The answer is the return value of the function $\textit{dfs}(0, n - 1)$.

The time complexity is $O(n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array `nums`.
The time complexity is $O(n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array $\textit{nums}$.

<!-- tabs:start -->

Expand All @@ -84,13 +84,11 @@ The time complexity is $O(n)$, and the space complexity is $O(\log n)$. Here, $n
# self.right = right
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
def dfs(l, r):
def dfs(l: int, r: int) -> Optional[TreeNode]:
if l > r:
return None
mid = (l + r) >> 1
left = dfs(l, mid - 1)
right = dfs(mid + 1, r)
return TreeNode(nums[mid], left, right)
return TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r))

return dfs(0, len(nums) - 1)
```
Expand Down Expand Up @@ -126,9 +124,7 @@ class Solution {
return null;
}
int mid = (l + r) >> 1;
TreeNode left = dfs(l, mid - 1);
TreeNode right = dfs(mid + 1, r);
return new TreeNode(nums[mid], left, right);
return new TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r));
}
}
```
Expand All @@ -150,14 +146,12 @@ class Solution {
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
function<TreeNode*(int, int)> dfs = [&](int l, int r) -> TreeNode* {
auto dfs = [&](this auto&& dfs, int l, int r) -> TreeNode* {
if (l > r) {
return nullptr;
}
int mid = (l + r) >> 1;
auto left = dfs(l, mid - 1);
auto right = dfs(mid + 1, r);
return new TreeNode(nums[mid], left, right);
return new TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r));
};
return dfs(0, nums.size() - 1);
}
Expand All @@ -182,8 +176,7 @@ func sortedArrayToBST(nums []int) *TreeNode {
return nil
}
mid := (l + r) >> 1
left, right := dfs(l, mid-1), dfs(mid+1, r)
return &TreeNode{nums[mid], left, right}
return &TreeNode{nums[mid], dfs(l, mid-1), dfs(mid+1, r)}
}
return dfs(0, len(nums)-1)
}
Expand All @@ -207,16 +200,14 @@ func sortedArrayToBST(nums []int) *TreeNode {
*/

function sortedArrayToBST(nums: number[]): TreeNode | null {
const n = nums.length;
if (n === 0) {
return null;
}
const mid = n >> 1;
return new TreeNode(
nums[mid],
sortedArrayToBST(nums.slice(0, mid)),
sortedArrayToBST(nums.slice(mid + 1)),
);
const dfs = (l: number, r: number): TreeNode | null => {
if (l > r) {
return null;
}
const mid = (l + r) >> 1;
return new TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r));
};
return dfs(0, nums.length - 1);
}
```

Expand All @@ -241,23 +232,24 @@ function sortedArrayToBST(nums: number[]): TreeNode | null {
// }
// }
// }
use std::cell::RefCell;
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
fn to_bst(nums: &Vec<i32>, start: usize, end: usize) -> Option<Rc<RefCell<TreeNode>>> {
if start >= end {
return None;
}
let mid = start + (end - start) / 2;
Some(Rc::new(RefCell::new(TreeNode {
val: nums[mid],
left: Self::to_bst(nums, start, mid),
right: Self::to_bst(nums, mid + 1, end),
})))
}

pub fn sorted_array_to_bst(nums: Vec<i32>) -> Option<Rc<RefCell<TreeNode>>> {
Self::to_bst(&nums, 0, nums.len())
fn dfs(nums: &Vec<i32>, l: usize, r: usize) -> Option<Rc<RefCell<TreeNode>>> {
if l > r {
return None;
}
let mid = (l + r) / 2;
if mid >= nums.len() {
return None;
}
let mut node = Rc::new(RefCell::new(TreeNode::new(nums[mid])));
node.borrow_mut().left = dfs(nums, l, mid - 1);
node.borrow_mut().right = dfs(nums, mid + 1, r);
Some(node)
}
dfs(&nums, 0, nums.len() - 1)
}
}
```
Expand All @@ -283,14 +275,46 @@ var sortedArrayToBST = function (nums) {
return null;
}
const mid = (l + r) >> 1;
const left = dfs(l, mid - 1);
const right = dfs(mid + 1, r);
return new TreeNode(nums[mid], left, right);
return new TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r));
};
return dfs(0, nums.length - 1);
};
```

#### C#

```cs
/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
public class Solution {
private int[] nums;

public TreeNode SortedArrayToBST(int[] nums) {
this.nums = nums;
return dfs(0, nums.Length - 1);
}

private TreeNode dfs(int l, int r) {
if (l > r) {
return null;
}
int mid = (l + r) >> 1;
return new TreeNode(nums[mid], dfs(l, mid - 1), dfs(mid + 1, r));
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Loading

0 comments on commit 719049e

Please sign in to comment.