diff --git a/alg.md b/alg.md index edf7eec7bf0e563425234584f561a549eabd0f46..5fb016f4c98cd49254a9f81013bd1ad0e9bbe25c 100644 --- a/alg.md +++ b/alg.md @@ -1,148 +1,84 @@ -# 算法设计第二次作业 - -### 输出数组中第K大的数 - -###### 1.测试数据生成 - -```c++ -int num[5] = { 0 }; - while (num[4] == 0) - { - srand((int)time(0)); // 产生随机种子 把0换成NULL也行 - for (int i = 0; i < 5; i++) - { - int a = (rand() % 100) + 1; - num[i] = a; - } - } - cout << "生成随机数组:" << endl; - for (int i = 0; i < 5; i++) - cout << num[i] << ' '; - cout << endl; -``` +# 解题报告:构建最大二叉树 -思路:srand()产生随机种子,以此产生随机数。将num[]初始化为0,再将数组各元素替换成生成的随机数。 - -###### 2.算法实现及测试 - -```c++ -void merge(int* a, int low, int mid, int hight) //合并函数 -{ - int* b = new int[hight - low + 1]; //用 new 申请一个辅助函数 - int i = low, j = mid + 1, k = 0; // k为 b 数组的小标 - while (i <= mid && j <= hight) - { - if (a[i] <= a[j]) - { - b[k++] = a[i++]; //按从小到大存放在 b 数组里面 - } - else - { - b[k++] = a[j++]; - } - } - while (i <= mid) // j 序列结束,将剩余的 i 序列补充在 b 数组中 - { - b[k++] = a[i++]; - } - while (j <= hight)// i 序列结束,将剩余的 j 序列补充在 b 数组中 - { - b[k++] = a[j++]; - } - k = 0; //从小标为 0 开始传送 - for (int i = low; i <= hight; i++) //将 b 数组的值传递给数组 a - { - a[i] = b[k++]; - } - delete[]b; // 辅助数组用完后,将其的空间进行释放(销毁) -} - - - -void mergesort(int* a, int low, int hight) //归并排序 -{ - if (low < hight) - { - int mid = (low + hight) / 2; - mergesort(a, low, mid); //对 a[low,mid]进行排序 - mergesort(a, mid + 1, hight); //对 a[mid+1,hight]进行排序 - merge(a, low, mid, hight); //进行合并操作 - } -} - -int main() -{ - int num[5] = { 0 }; - while (num[4] == 0) - { - srand((int)time(0)); // 产生随机种子 把0换成NULL也行 - for (int i = 0; i < 5; i++) - { - int a = (rand() % 100) + 1; - num[i] = a; - } - } - cout << "生成随机数组:" << endl; - for (int i = 0; i < 5; i++) - cout << num[i] << ' '; - cout << endl; - - mergesort(num, 0, 4); - cout << "归并排序后的结果:" << endl; - for (int i = 0; i < 5; i++) - cout << num[i] << ' '; - cout << endl; - - int k; - cout << "输入k:"; - cin >> k; - if (k > 4) { - cout << "超过数组大小!"; - return 0; - } - cout << "第k大的数为:"; - cout << num[k - 1]; - - - return 0; - - -} -``` +## 题目描述 -*思路*:归并排序,将产生的随机数组进行排序。输出第K-1个数即可。 +​ 给定一个不重复的整数数组 `nums`,构建一个最大二叉树,其中根节点的值为 `nums` 中的最大值,左子树是构建在最大值左边的子数组的最大二叉树,右子树是构建在最大值右边的子数组的最大二叉树。 -**归并排序**:归并排序是比较稳定的排序方法。它的基本思想是把待排序的元素分解成两个规模大致相等的子序列。如果不易分解,将得到的子序列继续分解,直到子序列中包含的元素个数为1。因为单个元素的序列本身就是有序的,此时便可以进行合并,从而得到一个完整的有序序列。 +## 思路分析 -**分治算法**:将一个大问题分成多个规模较小的子问题,分而治之。 +​ 对于一个不重复的整数数组 `nums`,我们可以通过以下步骤构建一个最大二叉树: -###### 3.性能分析 +1. 找到数组中的最大值及其索引。 +2. 创建根节点,其值为最大值。 +3. 递归地在最大值左边的子数组前缀上构建左子树。 +4. 递归地在最大值右边的子数组后缀上构建右子树。 +5. 返回构建好的最大二叉树的根节点。 +## 代码实现 +​ 下面是python代码实现,其中`TreeNode`类定义了二叉树节点的结构,`constructMaximumbinaryTree`函数接收一个整数数组 `nums`,返回该数组构建的最大二叉树的根节点。在函数内部,首先判断如果 `nums` 数组为空,则直接返回 `None`。否则,找到数组中的最大值及其索引,创建根节点,其值为最大值。然后,递归地在最大值左边的子数组前缀上构建左子树,递归地在最大值右边的子数组后缀上构建右子树。最后,返回构建好的最大二叉树的根节点。 -**空间性能**: -$$ -O(log~2^n)+O(n) -$$ -**时间性能**: -$$ -O(nlogn) -$$ +```python +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +def constructMaximumBinaryTree(nums): + # 如果数组为空,则返回None + if not nums: + return None + + max_num = max(nums) -###### 4.代码测试 + # 找到数组中的最大值及其索引 + idx = nums.index(max_num) -![](C:\Users\20292\Desktop\V37C4D75XVO(KJ0Z98XR98W.png) + # 创建根节点,其值为最大值 + root = TreeNode(max_num) -###### 5.心得体会 + # 递归地在最大值左边的子数组前缀上构建左子树 + root.left = constructMaximumBinaryTree(nums[:idx]) -git用起来没有第一次那么坎坷,基本的操作都没有问题,也在不断地用一些新东西。这次代码部分我用了自己更加熟悉的c++,写起来更加流畅一点点。 + # 递归地在最大值右边的子数组后缀上构建右子树 + root.right = constructMaximumBinaryTree(nums[idx+1:]) + + # 返回构建好的最大二叉树的根节点 + return root -###### 6.实验环境 +``` + +## 测试示例 + +​ 下面是一个测试代码的例子: + +```python +import alg +nums = [3, 2, 1, 6, 0, 5] +# 构建最大二叉树 +root = alg.constructMaximumBinaryTree(nums) +# 前序遍历二叉树 +def preorderTraversal(root): + res = [] + def helper(root): + # 如果树为空,则返回None + if not root: + return None + res.append(root.val) + helper(root.left) + helper(root.right) + helper(root) + return res +# 打印遍历结果 +print(preorderTraversal(root)) +``` -win11. +​ 这个测试代码将一个整数数组传递给 `constructMaximumBinaryTree` 函数,得到该数组构建的最大二叉树的根节点。然后,使用 `preorderTraversal` 函数进行前序遍历,并打印遍历结果。运行该测试代码将输出 `[6,3,2,1,5,0]`,即最大二叉树的前序遍历结果。 -python3.11 +## 时间复杂度分析 -vs2022 +​ 对于一个长度为 `n` 的不重复的整数数组 `nums`,构建最大二叉树的时间复杂度为 $O(n\log n)$。 -git. +​ 在构建最大二叉树的过程中,每个节点最多会被访问两次,因此时间复杂度为 $O(n)$。而在最坏情况下,数组中的每个数都会成为树的根节点,因此二叉树的深度为 $O(n)$,所以总的时间复杂度为 $O(n\log n)$。 diff --git a/gen.py b/gen.py index 2c00ed37f2b65d6df42614c1016f68ab2241b8da..1c16f48d7f6b44ce2ec650a8a22ff7dadd368a72 100644 --- a/gen.py +++ b/gen.py @@ -1 +1,4 @@ nums = [3,2,1,6,0,5] + + + diff --git "a/\350\247\243\351\242\230\346\212\245\345\221\212\357\274\232\346\236\204\345\273\272\346\234\200\345\244\247\344\272\214\345\217\211\346\240\221.md" "b/\350\247\243\351\242\230\346\212\245\345\221\212\357\274\232\346\236\204\345\273\272\346\234\200\345\244\247\344\272\214\345\217\211\346\240\221.md" deleted file mode 100644 index 5f220365f0abd9958b32cf7e80e0c72187e98198..0000000000000000000000000000000000000000 --- "a/\350\247\243\351\242\230\346\212\245\345\221\212\357\274\232\346\236\204\345\273\272\346\234\200\345\244\247\344\272\214\345\217\211\346\240\221.md" +++ /dev/null @@ -1,85 +0,0 @@ -# 解题报告:构建最大二叉树 - -## 题目描述 - -​ 给定一个不重复的整数数组 `nums`,构建一个最大二叉树,其中根节点的值为 `nums` 中的最大值,左子树是构建在最大值左边的子数组的最大二叉树,右子树是构建在最大值右边的子数组的最大二叉树。 - -## 思路分析 - -​ 对于一个不重复的整数数组 `nums`,我们可以通过以下步骤构建一个最大二叉树: - -1. 找到数组中的最大值及其索引。 -2. 创建根节点,其值为最大值。 -3. 递归地在最大值左边的子数组前缀上构建左子树。 -4. 递归地在最大值右边的子数组后缀上构建右子树。 -5. 返回构建好的最大二叉树的根节点。 - -## 代码实现 - -​ 下面是python代码实现,其中`TreeNode`类定义了二叉树节点的结构,`constructMaximumbinaryTree`函数接收一个整数数组 `nums`,返回该数组构建的最大二叉树的根节点。在函数内部,首先判断如果 `nums` 数组为空,则直接返回 `None`。否则,找到数组中的最大值及其索引,创建根节点,其值为最大值。然后,递归地在最大值左边的子数组前缀上构建左子树,递归地在最大值右边的子数组后缀上构建右子树。最后,返回构建好的最大二叉树的根节点。 - -```python -# Definition for a binary tree node. -class TreeNode: - def __init__(self, val=0, left=None, right=None): - self.val = val - self.left = left - self.right = right - -def constructMaximumBinaryTree(nums): - # 如果数组为空,则返回None - if not nums: - return None - - max_num = max(nums) - - # 找到数组中的最大值及其索引 - idx = nums.index(max_num) - - # 创建根节点,其值为最大值 - root = TreeNode(max_num) - - # 递归地在最大值左边的子数组前缀上构建左子树 - root.left = constructMaximumBinaryTree(nums[:idx]) - - # 递归地在最大值右边的子数组后缀上构建右子树 - root.right = constructMaximumBinaryTree(nums[idx+1:]) - - # 返回构建好的最大二叉树的根节点 - return root - -``` - -## 测试示例 - -​ 下面是一个测试代码的例子: - -```python -import alg -nums = [3, 2, 1, 6, 0, 5] -# 构建最大二叉树 -root = alg.constructMaximumBinaryTree(nums) -# 前序遍历二叉树 -def preorderTraversal(root): - res = [] - def helper(root): - # 如果树为空,则返回None - if not root: - return None - res.append(root.val) - helper(root.left) - helper(root.right) - helper(root) - return res -# 打印遍历结果 -print(preorderTraversal(root)) -``` - -​ 这个测试代码将一个整数数组传递给 `constructMaximumBinaryTree` 函数,得到该数组构建的最大二叉树的根节点。然后,使用 `preorderTraversal` 函数进行前序遍历,并打印遍历结果。运行该测试代码将输出 `[6,3,2,1,5,0]`,即最大二叉树的前序遍历结果。 - -## 时间复杂度分析 - -​ 对于一个长度为 `n` 的不重复的整数数组 `nums`,构建最大二叉树的时间复杂度为 $O(n\log n)$。 - -​ 在构建最大二叉树的过程中,每个节点最多会被访问两次,因此时间复杂度为 $O(n)$。而在最坏情况下,数组中的每个数都会成为树的根节点,因此二叉树的深度为 $O(n)$,所以总的时间复杂度为 $O(n\log n)$。 -