From 4d67d29412d30ce75f9e78462d8c6d479ea05abc Mon Sep 17 00:00:00 2001 From: ranwenjie Date: Sun, 14 Nov 2021 22:42:14 +0800 Subject: [PATCH] update dp --- 4 Tree/2-二叉查找树/二叉查找树.md | 14 ++++-- 8 Algorithms Analysis/动态规划.md | 43 ++++++++++++++----- 9 Algorithms Job Interview/4.2 数值-指数.md | 41 ++++++++++++++---- 9 Algorithms Job Interview/5.4 数列-查找.md | 31 +++++++++++++ 9 Algorithms Job Interview/7 二叉树.md | 6 ++- 9 Algorithms Job Interview/7.1 二叉树-遍历.md | 25 ++++++++++- 9 Algorithms Job Interview/7.5 二叉搜索树.md | 27 ++++++++++++ 7 files changed, 161 insertions(+), 26 deletions(-) create mode 100644 9 Algorithms Job Interview/7.5 二叉搜索树.md diff --git a/4 Tree/2-二叉查找树/二叉查找树.md b/4 Tree/2-二叉查找树/二叉查找树.md index 0a47375..3ce4c39 100644 --- a/4 Tree/2-二叉查找树/二叉查找树.md +++ b/4 Tree/2-二叉查找树/二叉查找树.md @@ -1,12 +1,15 @@ # 二叉查找树BST -二叉查找树(Binary search tree),也叫`有序二叉树(Ordered binary tree)`,`排序二叉树(Sorted binary tree)`。是指一个空树或者具有下列性质的二叉树: +二叉查找树(Binary search tree),也叫`有序二叉树(Ordered binary tree)`,`排序二叉树(Sorted binary tree)`。 + +是指一个空树或者具有下列性质的二叉树: 1. 若任意节点的左子树不为空,则左子树上所有的节点值小于它的根节点值 2. 若任意节点的右子树不为空,则右子树上所有节点的值均大于它的根节点的值 3. 任意节点左右子树也为二叉查找树 4. 没有键值(key)相等的节点 + 有序的二叉查找树,中序遍历结果是递增的。 @@ -23,12 +26,15 @@ ``` +### 删除节点 + 删除节点,需要重建排序树 1) 删除节点是叶子节点(分支为0),结构不破坏 2)删除节点只有一个分支(分支为1),结构也不破坏 - 3)删除节点有2个分支,此时删除节点 + 3)删除节点有2个分支,此时删除节点 ; 需要重建树 + 思路一: 选左子树的最大节点,或右子树最小节点替换 ``` @@ -55,6 +61,7 @@ int bisearch_tree_delete(BiSearchTree **tree,ElemType node){ printf("树为空,或想要删除的节点不存在\n"); return -1; } + //该节点为叶子节点,直接删除 if (!target->rChild && !target->lChild) { @@ -86,7 +93,8 @@ int bisearch_tree_delete(BiSearchTree **tree,ElemType node){ target->rChild=target->rChild->rChild; free(del); - } + } + else{ //左右子树均不空,p,t 2个指针一前以后,将左子树最大的节点(肯定是一个最右的节点)替换到删除的节点后,还需要处理左子树最大节点的左子树 BiSearchTree *p=target,*t=target->lChild; diff --git a/8 Algorithms Analysis/动态规划.md b/8 Algorithms Analysis/动态规划.md index 01a2222..c2ff383 100644 --- a/8 Algorithms Analysis/动态规划.md +++ b/8 Algorithms Analysis/动态规划.md @@ -8,7 +8,7 @@ DP通常基于一个递推公式及一个(或多个)初始状态,当前子问 动态规划算法的关键在于解决冗余,以空间换时间的技术,需要存储过程中的各种状态。可以看着是`分治算法`+`解决冗余` -动态规划算法也可以说是 `记住求过的解来节省时间` +动态规划算法也可以说是 `记住求过的解来节省时间` ; 比如 Fibonacci数列 中,先直接从最小,最简单的 f(1) , f(2) 开始,自低向上一直到 f(20) , 这就是动态规划的思路 【初始状态】→【决策1】→【决策2】→…→【决策n】→【结束状态】 @@ -21,16 +21,20 @@ DP通常基于一个递推公式及一个(或多个)初始状态,当前子问 动态规划的核心思想就是穷举求最值; 动态规划问题的一般形式就是`求最值`,动态规划其实是运筹学的一种最优化方法,只不过在计算机问题上应用比较多,比如说: -* 最长递增子序列 (LIS Longest Increasing Subsequence) -* 最小编辑距离 -* 0-1 背包问题 -* 凑零钱问题 -* 股票问题 -* 接雨水问题 -* Fibonacci数列 +* Fibonacci数列 [代码参考这里 递归](./递归.md) +* 凑零钱问题 +* 股票问题 [代码参考这里](https://github.com/nonstriater/deep-in-java/blob/master/src/main/java/com/nonstriater/deepinjava/algo/list/stock/BestChance.java) +* 二叉树的最近公共祖先 [代码参考这里](https://github.com/nonstriater/deep-in-java/blob/master/src/main/java/com/nonstriater/deepinjava/algo/tree/CommonParent.java) +* 链表翻转 [代码参考这里](https://github.com/nonstriater/deep-in-java/blob/master/src/main/java/com/nonstriater/deepinjava/algo/link/ReverseLink.java) +* 接雨水问题 * 青蛙跳阶问题: 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 10 级的台阶总共有多少种跳法。 -* 二叉树的最近公共祖先 -* 链表翻转 +* 最小编辑距离 +* 最长递增子序列 (LIS Longest Increasing Subsequence) +* 0-1 背包问题 + + + +[更多动态规划案例代码实现参考deep-in-java])(https://github.com/nonstriater/deep-in-java/tree/master/src/main/java/com/nonstriater/deepinjava/algo/framework/dynamic) ``` @@ -69,7 +73,7 @@ DP 和 回溯法 都会用到递归 * 划分问题 * 状态 -* 状态转移方程, 这一步最为困难 +* 状态转移方程, 这一步最为困难 ; 暴力解法就是状态转移方程 * 状态压缩 @@ -87,6 +91,23 @@ for 状态1 in 状态1的所有取值: +## 凑零钱问题 + +凑零钱问题[视频解读参考这里]() + +如果使用贪心策略,并不能得到最优解。 + + + +```Java + +``` + + + + + + diff --git a/9 Algorithms Job Interview/4.2 数值-指数.md b/9 Algorithms Job Interview/4.2 数值-指数.md index 371b804..247983c 100644 --- a/9 Algorithms Job Interview/4.2 数值-指数.md +++ b/9 Algorithms Job Interview/4.2 数值-指数.md @@ -11,6 +11,19 @@ 不需要考虑溢出。 + +用例: + +``` +2^3 = 8 +0^3 = 0 +2^0 = 1 +2^-3 = 1/(2^3) = 0.125 +0^-3 +``` + + + 分析:这是一道看起来很简单的问题。可能有不少的人在看到题目后30秒写出如下的代码: ``` double Power(double base, int exponent) @@ -35,15 +48,6 @@ double Power(double base, int exponent) 2^1 = 2 ``` -用例: - -``` -2 3 = 8 -0 3 = 0 -2 0 = 1 -2 -3 = 1/(2^3) = 0.125 -0 -3 -``` 使用递归实现的代码示例: @@ -62,6 +66,25 @@ double Power(double base, unsigned int exponent) ``` +## Sqrt(x) + +给你一个非负整数 x ,计算并返回 x 的 算术平方根 。由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 + + +示例 1: +``` +输入:x = 4 +输出:2 +``` +示例 2: +``` +输入:x = 8 +输出:2 +解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。 +``` + + + ## 求根号2的值 并且按照我的需要列出指定小数位,比如根号2是1.141 我要列出1位小数就是1.1 2位就是1.14, 1000位就是1.141...... 等。。 diff --git a/9 Algorithms Job Interview/5.4 数列-查找.md b/9 Algorithms Job Interview/5.4 数列-查找.md index f1763fa..48bd250 100644 --- a/9 Algorithms Job Interview/5.4 数列-查找.md +++ b/9 Algorithms Job Interview/5.4 数列-查找.md @@ -141,4 +141,35 @@ int one_appear_count(int n); +## 搜索旋转排序数组 + + +整数数组 nums 按升序排列,数组中的值 互不相同 。 + +在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。 + +给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。 + + +示例 1: + +``` +输入:nums = [4,5,6,7,0,1,2], target = 0 +输出:4 +``` + +示例 2: +``` +输入:nums = [4,5,6,7,0,1,2], target = 3 +输出:-1 +``` + + + + + + + + + diff --git a/9 Algorithms Job Interview/7 二叉树.md b/9 Algorithms Job Interview/7 二叉树.md index 1bc6d32..58bac03 100644 --- a/9 Algorithms Job Interview/7 二叉树.md +++ b/9 Algorithms Job Interview/7 二叉树.md @@ -107,8 +107,7 @@ TreeNode invertTree(TreeNode root) { - -## 二叉树两个结点的最低共同父结点 +## 二叉树两个结点的最低共同父结点 (最近公共祖先) 设计一个算法,找出二叉树上任意两个结点的最近共同父结点。复杂度如果是O(n2)则不得分 @@ -119,6 +118,9 @@ TreeNode invertTree(TreeNode root) { + + + ## 求一个二叉树中任意两个节点间的最大距离 两个节点的距离的定义是 这两个节点间边的个数,比如某个孩子节点和父节点间的距离是1,和相邻兄弟节点间的距离是2,优化时间空间复杂度。 diff --git a/9 Algorithms Job Interview/7.1 二叉树-遍历.md b/9 Algorithms Job Interview/7.1 二叉树-遍历.md index f072186..c98ae50 100644 --- a/9 Algorithms Job Interview/7.1 二叉树-遍历.md +++ b/9 Algorithms Job Interview/7.1 二叉树-遍历.md @@ -49,13 +49,30 @@ 分析:这道题本质上还是考查二元树的遍历。对于一颗完全二叉树,要求给所有节点加上一个pNext指针,指向同一层的相邻节点;如果当前节点已经是该层的最后一个节点,则将pNext指针指向NULL;给出程序实现,并分析时间复杂度和空间复杂度。 +## 二元树的最小深度 + + +例如:输入二元树: +``` + + 10 + / \ + 6 14 + / \ + 12 16 +``` + +输出该树的最小深度2。 + + ## 判断整数序列是不是二元查找树的后序遍历结果 题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。 如果是返回true,否则返回false。 -例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果: + +例如输入`5、7、6、9、11、10、8`,由于这一整数序列是如下树的后序遍历结果: ``` 8 / \ @@ -66,3 +83,9 @@ 因此返回true。如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。 + + + + + + diff --git a/9 Algorithms Job Interview/7.5 二叉搜索树.md b/9 Algorithms Job Interview/7.5 二叉搜索树.md new file mode 100644 index 0000000..31b323c --- /dev/null +++ b/9 Algorithms Job Interview/7.5 二叉搜索树.md @@ -0,0 +1,27 @@ +# 二叉搜索树 + +关于二叉查找树特性[参考这里](../4%20Tree/2-二叉查找树/二叉查找树.md) + +## 验证二叉搜索树 + + +## 二叉搜索树中的节点搜索 + + +## 二叉搜索树中的插入操作 + + +## 删除二叉搜索树中的节点 + + + + + + + + + + + + +