动态规划 二叉树 贪心算法

master
kn5886348135 3 years ago
parent 2d8ff7b91b
commit 80e4f5b42a

@ -110,6 +110,8 @@
  规定1和A对应、2和B对应、3和C对应...26和Z对应。那么一个数字字符串比如"111”就可以转化为:"AAA"、"KA"和"AK"。给定一个只有数字字符组成的字符串str返回有多少种转化结果
#### 剪裁贴纸
  给定一个字符串str给定一个字符串类型的数组arr出现的字符都是小写英文。arr每一个字符串代表一张贴纸你可以把单个字符剪开使用目的是拼出str来。返回需要至少多少张贴纸可以完成这个任务。
  例子str= "babac"arr = {"ba","c","abcd"} ba + ba + c 3 abcd + abcd 2 abcd+ba 2 所以返回2

@ -1,16 +1,85 @@
#### 合并K个升序链表 LeetCode2
## <center>二叉树</center>
使用PriorityQueue保存各链表的头结点每次prorityQueue.poll()弹出最小值注意单链表的next指针和中间变量。循环终止条件为优先级队列变空。
递归序 每个节点都到达三次
二叉树
先序遍历 头左右
中序遍历 左头右
后序遍历 左右头
#### 二叉树的先序、中序、后序遍历
递归序 每个节点都到达三次
先序:任何子树的处理顺序都是,先头节点、再左子树、然后右子树
中序:任何子树的处理顺序都是,先左子树、再头节点、然后右子树
后序:任何子树的处理顺序都是,先左子树、再右子树、然后头节点
#### 递归方式实现二叉树的先序、中序、后序遍历
1理解递归序
2先序、中序、后序都可以在递归序的基础上加工出来
3第一次到达一个节点就打印就是先序、第二次打印即中序、第三次即后序
#### X 祖先节点 交集
<br />
<br />
&emsp;&emsp;X是一棵二叉树的某一个节点A是二叉树先序遍历X的左边部分B是二叉树后序遍历X右边部分AB相交的结果是且仅是X的所有父节点。
1、X的所有父节点在先序遍历的左边X的所有父节点在后序遍历的右边交集一定包含所有父节点
2、X的所有子节点在先序遍历的左边X的所有子节点在后序遍历的左边交集一定不包含所有子节点
3、A不包含所有祖先节点的右兄弟节点B不包含所有祖先节点的左兄弟节点
&emsp;&emsp;X的所有祖先节点、X自己、X的子节点、X或者X的父节点作为左树的右兄节点、X或者X的父节点作为右树的左兄节点
<br />
<br />
#### 非递归方式实现二叉树的先序、中序、后序遍历
1任何递归函数都可以改成非递归
2自己设计压栈的来实现
#### 实现二叉树的按层遍历
1其实就是宽度优先遍历用队列
2可以通过设置flag变量的方式来发现某一层的结束
#### 实现二叉树的序列化和反序列化
1先序方式序列化和反序列化
2按层方式序列化和反序列化
#### 将多叉树编码为二叉树 LeetCode431
#### 打印二叉树
#### 二叉树的宽度
求二叉树最宽的层有多少个节点
#### 找出某个节点的后继节点
&emsp;&emsp;二叉树结构如下定义:
```Java
Class Node {
V value;
Node left;
Node right;
Node parent;
}
```
&emsp;&emsp;给你二叉树中的某个节点,返回该节点的后继节点。
#### 折纸
&emsp;&emsp;请把一段纸条竖着放在桌子上然后从纸条的下边向上方对折1次压出折痕后展开。此时折痕是凹下去的即折痕突起的方向指向纸条的背面。 如果从纸条的下边向上方连续对折2次压出折痕后展开此时有三条折痕从上到下依次是下折痕、下折痕和上折痕。
给定一个输入参数N代表纸条都从下边向上方连续对折N次。 请从上到下打印所有折痕的方向。
例如:N=1时打印: down N=2时打印: down down up
主要解题思路是递归
二叉树的递归套路
1假设以X节点为头假设可以向X左树和X右树要任何信息
2在上一步的假设下讨论以X为头节点的树得到答案的可能性最重要
3列出所有可能性后确定到底需要向左树和右树要什么样的信息
4把左树信息和右树信息求全集就是任何一棵子树都需要返回的信息S
5递归函数都返回S每一棵子树都这么要求
6写代码在代码中考虑如何把左树的信息和右树信息整合出整棵树的信息
#### 判断两颗二叉树是否相同 LeetCode100
#### 判断一个二叉树是否对称 LeetCode101
@ -27,6 +96,7 @@
#### 平衡二叉树 LeetCode110
给定一棵二叉树的头节点head返回这颗二叉树是不是平衡二叉树
判断二叉树是否是平衡二叉树
左子树的高度和右子树的高度相差不超过1则称为平衡二叉树。
@ -39,12 +109,52 @@
#### 达标路径总和 LeetCode113
X是一棵二叉树的某一个节点A是二叉树先序遍历X的左边部分B是二叉树后序遍历X右边部分AB相交的结果是且仅是X的所有父节点。
1、X的所有父节点在先序遍历的左边X的所有父节点在后序遍历的右边交集一定包含所有父节点
2、X的所有子节点在先序遍历的左边X的所有子节点在后序遍历的左边交集一定不包含所有子节点
3、A不包含所有祖先节点的右兄弟节点B不包含所有祖先节点的左兄弟节点
#### 二叉树的最大距离
给定一颗二叉树的头结点,任何两个节点之间都存在距离,返回整颗二叉树的最大距离。
#### 判断完全二叉树
判断二叉树是否是完全二叉树
按照二叉树的定义判断,逐行遍历
递归套路
#### 满二叉树
给定一棵二叉树的头节点head返回这颗二叉树是不是满二叉树
#### 最大的二叉搜索子树
给定一棵二叉树的头节点head返回这颗二叉树中最大的二叉搜索子树的头节点。
#### 最大的二叉搜索子树大小
给定一棵二叉树的头节点head返回这颗二叉树中最大的二叉搜索子树的大小。
#### 最低公共祖先
给定一棵二叉树的头节点head和另外两个节点a和b。返回a和b的最低公共祖先。
a、b可能在head的左右子树也可能在同一棵子树。
使用中间变量
1、遍历整棵树用map保存所有节点的父节点
2、遍历a的所有父节点用set保存
3、遍历b的所有父节点看set中是否存在
后序遍历递归套路
#### 派对的最大快乐值
&emsp;&emsp;员工信息的定义如下:
X的所有祖先节点、X自己、X的子节点、X或者X的父节点作为左树的右兄节点、X或者X的父节点作为右树的左兄节点
```Java
class Employee {
public int happy; // 这名员工可以带来的快乐值
List<Employee> subordinates; // 这名员工有哪些直接下级
}
```
给定一颗二叉树的头结点,任何两个节点之间都存在距离,返回整颗二叉树的最大距离
二叉树node的a、b两个节点的最低公共祖先可以使用递归套路也可以使用set或者map结合后序遍历实现
&emsp;&emsp;公司的每个员工都符合 Employee 类的描述。整个公司的人员结构可以看作是一棵标准的、 没有环的多叉树。树的头节点是公司唯一的老板。除老板之外的每个员工都有唯一的直接上级。 叶节点是没有任何下属的基层员工(subordinates列表为空),除基层员工外,每个员工都有一个或多个直接下级。
&emsp;&emsp;这个公司现在要办party你可以决定哪些员工来哪些员工不来规则
&emsp;&emsp;1.如果某个员工来了,那么这个员工的所有直接下级都不能来
&emsp;&emsp;2.派对的整体快乐值是所有到场员工快乐值的累加
&emsp;&emsp;3.你的目标是让派对的整体快乐值尽量大
&emsp;&emsp;给定一棵多叉树的头节点boss请返回派对的最大快乐值。

@ -1,10 +1,59 @@
贪心算法
## <center>贪心算法</center>
a.b<<b.ab.c<<c.b a.c<<c.a
### 贪心算法
贪心算法不需要证明,使用对数器证明
* 1最自然智慧的算法
* 2用一种局部最功利的标准总是做出在当前看来是最好的选择
* 3难点在于证明局部最功利的标准可以得到全局最优解
* 4对于贪心算法的学习主要以增加阅历和经验为主
分割金条60长度分成10、20、30
每次切割最大长度的反例97、98 和 100、99
反例的证明就是哈夫曼编码
将所有分割后的长度放入小根堆,每次获取两个长度相加然后放回小根堆,重复
### 贪心求解的标准过程
* 1分析业务
* 2根据业务逻辑找到不同的贪心策略
* 3对于能举出反例的策略直接跳过不能举出反例的策略要证明有效性这往往是特别困难的要求数学能力很高且不具有统一的技巧性
### 贪心算法的解题套路
* 1实现一个不依靠贪心策略的解法X可以用最暴力的尝试
* 2脑补出贪心策略A、贪心策略B、贪心策略C...
* 3用解法X和对数器用实验的方式得知哪个贪心策略正确
* 4不要去纠结贪心策略的证明
### 贪心算法常见问题
#### 最小字典序
&emsp;&emsp;给定一个由字符串组成的数组strs必须把所有的字符串拼接起来返回所有可能的拼接结果中字典序最小的结果。
&emsp;&emsp;a.b&lt;b.a并且b.c&lt;c.b 得到a.c&lt;c.a比较的传递性。
#### 分割金条
&emsp;&emsp;分割金条60长度分成10、20、30。一块金条切成两半是需要花费和长度数值一样的铜板的。比如长度为20的金条不管怎么切都要花费20个铜板。 一群人想整分整块金条,怎么分最省铜板?
&emsp;&emsp;例如,给定数组{10,20,30}代表一共三个人整块金条长度为60金条要分成102030三个部分。如果先把长度60的金条分成10和50花费60; 再把长度50的金条分成20和30花费50;一共花费110铜板。但如果先把长度60的金条分成30和30花费60;再把长度30金条分成10和20 花费30;一共花费90铜板。
&emsp;&emsp;输入一个数组,返回分割的最小代价。暂不考虑切割的顺序,如果考虑切割顺序需要使用动态规划和四边形不等式。
&emsp;&emsp;暴力尝试双层循环将i和j合并递归得到花费最后将最小的花费返回。
&emsp;&emsp;将所有分割后的长度放入小根堆,每次获取两个长度相加然后放回小根堆,重复直到小根堆只剩一个元素。
&emsp;&emsp;每次都切割最大长度的反例97、98 和 100、99。正确操作是第一次切割成100+99和98+97而不是切割成100和99+98+97。<font color="red">反例的证明就是哈夫曼编码。</font>
#### 点灯
&emsp;&emsp;给定一个字符串str只由X.两种字符构成。X表示墙不能放灯也不需要点亮。.表示居民点可以放灯需要点亮。如果灯放在i位置可以让i-1i和i+1三个位置被点亮。返回如果点亮str中所有需要点亮的位置至少需要几盏灯。
#### 安排会议室
&emsp;&emsp;一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。给你每一个项目开始的时间和结束的时间,你来安排宣讲的日程,要求会议室进行的宣讲的场次最多。返回最多的宣讲场次。
#### IPO
&emsp;&emsp;输入: 正数数组costs、正数数组profits、正数K、正数M
&emsp;&emsp;costs[i]表示i号项目的花费
&emsp;&emsp;profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润)
&emsp;&emsp;K表示你只能串行的最多做k个项目
&emsp;&emsp;M表示你初始的资金
&emsp;&emsp;说明: 每做完一个项目,马上获得的收益,可以支持你去做下一个项目。不能并行的做项目。
&emsp;&emsp;输出:你最后获得的最大钱数。

Loading…
Cancel
Save