树:

404. 左叶子之和

求所有左叶子结点之和
. 递归法
分析:递归法遍历结点,找左叶子结点
空指针判断
有左子节点?是叶子结点?是的话更新value的值 int sumOfLeftLeaves(TreeNode* root) {
if(!root) return ; // NULL
int value = ;
if(root->left){ //左子节点
if(!root->left->left && !root->left->right) //是不是叶子结点?
value = root->left->val ;
}
return value + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
} .非递归法遍历寻找所有左叶子结点 int sumOfLeftLeaves(TreeNode* root) {
if(!root) return ; //注意一定要处理空指针
int res = ;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
root = q.front();
q.pop();
if(root->left){ //左子节点
q.push(root->left);
if(!root->left->left && !root->left->right){ //是否为叶子结点
res += root->left->val;
}
}
if(root->right){
q.push(root->right);
}
}
return res;
}

671. Second Minimum Node In a Binary Tree

题意:求二叉树第二小值,没有返回-
分析:用set存所有节点,最终容量大于2,代表存在第二小值,输出*(++set.begin())
```
int findSecondMinimumValue(TreeNode* root) {
if(!root) return -;
int res = -;
queue<TreeNode* > q;
q.push(root);
set<int> s;
while (!q.empty())
{
root = q.front();
s.insert(root->val);
q.pop();
if (root->left) {
q.push(root->left);
}
if (root->right) {
q.push(root->right);
}
}
if(s.size() < ) res = -;
else res = *(++s.begin());
return res;
}

102. 二叉树的层次遍历

二叉树层次遍历且每层输出
算法记忆:一层一循环
```
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int> > res;
vector<int> tmp;
if(!root) return res;
queue<TreeNode*> q;
q.push(root);
int currentLevelTotalNum = ;
while(!q.empty())
{
tmp.clear();
currentLevelTotalNum = q.size();
while(currentLevelTotalNum--){ //一层一循环
root = q.front();
tmp.push_back(root->val);
q.pop();
if(root->left){
q.push(root->left);
}
if(root->right){
q.push(root->right);
}
}
res.push_back(tmp);
}
return res;
}
```

107. 二叉树的层次遍历 II

分析:在正序层析遍历基础上,用栈临时存一下

vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int> > res;
vector<int> tmp;
stack<vector<int> >tmps;
if(!root) return res;
queue<TreeNode*> q;
q.push(root);
int currentLevelTotalNum = ;
while(!q.empty())
{
tmp.clear();
currentLevelTotalNum = q.size();
while(currentLevelTotalNum--){ //一层一循环
root = q.front();
tmp.push_back(root->val);
q.pop();
if(root->left){
q.push(root->left);
}
if(root->right){
q.push(root->right);
}
}
tmps.push(tmp);
}
while(!tmps.empty()){
res.push_back(tmps.top());
tmps.pop();
}
return res;
}

637. 二叉树的层平均值

题意:求二叉树每层平均值(double)所组成的数组
分析:每层求和取平均值
```
vector<double> averageOfLevels(TreeNode* root) {
vector<double> res;
if(!root) return res;
queue<TreeNode* > q;
q.push(root);
int currentLevelTotalNum = , n = ;
double tmpd;
while(!q.empty()){
currentLevelTotalNum = q.size();
n = currentLevelTotalNum;
tmpd = ;
while(currentLevelTotalNum--){ //此层所有节点
root = q.front();
tmpd +=root->val;
q.pop();
if(root->left){
q.push(root->left);
}
if(root->right)
{
q.push(root->right);
}
}
tmpd /= n;
res.push_back(tmpd);
}
return res;
}
```

101. 对称二叉树

关键点在于递归比较。

题意:给定一个二叉树,检查它是否是它自己的镜像(即,围绕它的中心对称)。
分析:一个结点左子节点l,与右子节点r比较,递归的判断整棵树,l的左与r的右 且l的右跟r的左比较
抽取出递归模型如下
```
bool is(TreeNode* root1, TreeNode* root2){
if(!root1 && !root2) return true;
if(!root1) return false;
if(!root2) return false;
if(root1->val != root2->val){
return false;
}
return is(root1->left,root2->right) && is(root1->right,root2->left);
}
bool isSymmetric(TreeNode* root) {
if(!root) return true;
return is(root->left,root->right);
}
```

111. 二叉树的最小深度

题意:二叉树最小深度(从根节点到叶子结点的结点个数,包含两端)
分析:递归,
终结条件是 . root ==NULL . 叶子结点
分别计算左子树、右子树的长度
取最小值,因为加上本结点所以最终返回值+
```
int minDepth(TreeNode* root) {
if(!root) return ;
if(!root->left && !root->right)
return ;
int left,right;
if(root->left) left = minDepth(root->left);
else left = INT_MAX;
if(root->right) right = minDepth(root->right);
else right = INT_MAX;
return min(left,right) + ;
}
```

104. 二叉树的最大深度

题意:最大二叉树深度
分析:递归法
.终结条件:
. NULL
. 叶子结点
. 分别计算左右子树长度
. 返回max(left,right)+ 加1是因为加上本结点
```
int maxDepth(TreeNode* root) {
if(!root) return ;
if(!root->left && !root->right) return ;
int left, right;
if(root->left) left = maxDepth(root->left);
else left = INT_MIN;
if(root->right) right = maxDepth(root->right);
else right = INT_MIN;
return max(left,right) + ;
}
```

110. 平衡二叉树

题意:判断是否为平衡二叉树
分析:
本题是递归数深度遍历的一种应用。按照题目的意思,对于一个节点分别算出每个节点的左、右子树的深度,如果左、右子树深度差大于1,则可以该树非平衡。
那么递归每一个节点,一旦发现某一节点非平衡,就返回false,如果每一节点都平衡,则返回true:
```
//获取树的深度
int getDepth(TreeNode* root){
if(!root) return ;
return max(getDepth(root->left),getDepth(root->right)) + ;
}
//递归判断每个结点的子树是否满足长度只差不大于1
bool isBalanced(TreeNode* root) {
if(!root) return true;
if(abs(getDepth(root->left) - getDepth(root->right)) > ){
return false;
}
return isBalanced(root->left) && isBalanced(root->right);
}
```

144. 二叉树的前序遍历 +1 2

题目:二叉树,前序遍历,迭代法

分析:DFS,用到栈,一直沿着左指针将沿路节点压入栈内,当到尽头,弹出top结点,将其右子树压入,右子树同样是先沿着左指针压到尽头后,向右展

记忆:深搜栈右展

```
vector<int> res;
vector<int> preorderTraversal(TreeNode* root) {
//递归
if(root){
res.push_back(root->val);
preorderTraversal(root->left);
preorderTraversal(root->right);
} return res;
} vector<int> preorderTraversal(TreeNode* root) {
//迭代
vector<int> res;
if(!root) return res;
stack<TreeNode*> s;
while (!s.empty() || root != NULL)
{
if (root) { //至最左
res.push_back(root->val);
s.push(root);
root = root->left;
} else { //左到尽头,往右走
root = s.top();
s.pop();
root = root->right;
}
}
return res;
} ```

94. 中序遍历二叉树 1+2

题意: 二叉树中序遍历,迭代法

分析: DFS,利用栈,沿着左指针将一直到最左端的沿路所有节点依次压入栈中,每到到最左端向右展一下

记忆:深搜栈右展

```
vector<int> inorderTraversal(TreeNode* root) {
stack< TreeNode* > s;
TreeNode * p = root;
vector<int> tmp;
while(!s.empty() || p!=NULL){
while(p){ //到最左端
s.push(p);
p=p->left;
}
if(!s.empty()){ //右展一次
p=s.top();
tmp.push_back(p->val);
s.pop();
p=p->right;
}
}
return tmp;
} ```

145. 二叉树的后序遍历 1 2 + 迭代法

分析:同样用到栈

记忆:+21入栈,处理两情况

//递归法
```
vector<int> res;
vector<int> postorderTraversal(TreeNode* root) {
if(root){
postorderTraversal(root->left);
postorderTraversal(root->right);
res.push_back(root->val);
}
return res;
}
```
//迭代法
```
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
if(!root) return res;
stack<TreeNode* > s;
TreeNode *cur = root, *pre = NULL;
s.push(cur);
// 栈中的顺序是后序遍历的反序,先压入根,再压入右结点,左结点
while (!s.empty())
{
cur = s.top();
if((!cur->left && !cur->right) || (pre && (cur->left == pre || cur->right == pre))) //叶子结点直接处理 || 刚刚处理完左右结点
{
res.push_back(cur->val);
pre = cur;
s.pop();
}
else{
if(cur->right){
s.push(cur->right);
}
if (cur->left)
s.push(cur->left);
}
}
return res;
}
```

617. 合并二叉树

/*
题意:合并两棵二叉树,对应结点相加,否则补上
分析:递归实现
根节点都为空,return NULL
根节点都不为空,求和
根节点有一个空,补上
进一步分析左右子树
前三步就是抽取出来的子过程
*/
```
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if(!t1 && !t2) return NULL;
if (t1 && t2) {
t1->val += t2->val;
t2->val = t1->val;
}
else if (t1) {
t2 = new TreeNode(t1->val);
}
else if (t2) {
t1 = new TreeNode(t2->val);
}
t1->left = mergeTrees(t1->left,t2->left);
t1->right = mergeTrees(t1->right,t2->right);
return t1;
}
```

114. 二叉树转换链表

题意:二叉树转换链表;将所有结点编程右指针连接
分析:将前序遍历序列,顺序串联 ```
//迭代版,前序遍历
vector<TreeNode*> preOrder2(TreeNode* root) {
vector<TreeNode*> res;
if(!root) return res;
stack<TreeNode*> s;
TreeNode* p = root;
while(!s.empty() || p)
{
while(p){ //一直往左
res.push_back(p);
s.push(p);
p = p->left;
}
if(!s.empty()){ //右展
p = s.top();
s.pop();
p = p->right;
}
}
return res;
}
// 注意只需保留头指针,指针传递,传递方保留着头指针,他顺着访问就是了
void flatten(TreeNode* root) {
if(!root) return ;
//前序遍历结果
vector<TreeNode*> preOrderV = preOrder2(root);
int len = preOrderV.size();
root->left = NULL;
root->right = NULL;
//链表形成
for(int i=;i<len;i++)
{
root->right = preOrderV[i];
root = preOrderV[i];
root->left = NULL;
root->right =NULL;
}
}
```

112. 路径总和

/*
题意:路径总和,给一棵二叉树和一个整数sum,问是否存在从根节点到叶节点的路径,求和等于sum
分析:递归,和递减
*/
```
bool hasPathSum(TreeNode* root, int sum) {
if(!root) return false;
if(root->val == sum){ //恰好有叶节点满足
if(!root->left && !root->right){
return true;
}
}
return hasPathSum(root->left,sum-root->val) || hasPathSum(root->right,sum-root->val);
}
```

113. 路径总和 II

题意:找出一棵二叉树里,路径(根结点到叶结点)上结点之和等于sum的所有路径

分析:经典递归回溯问题,搜集路径上所有节点时,注意遇到结点push,用完节点pop

经典递归回溯
```
vector<vector<int> >result;
vector<int> path;
// 经典递归回溯问题
void findPath(TreeNode* root, int sum) {
if(!root) return ;
if(root->val == sum && !root->left && !root->right ) { //find a path equal sum && It's a leaf node
path.push_back(root->val);
result.push_back(path); // find a path
path.pop_back(); //!!
return ;
}
path.push_back(root->val); // 经过节点压入
findPath(root->left, sum - root->val);
findPath(root->right, sum - root->val);
path.pop_back(); // 对与此节点的左右子树都已经处理完,弹出此节点 !
}
vector<vector<int>> pathSum(TreeNode* root, int sum) {
vector<vector<int>> res;
if(!root) return res;
findPath(root, sum);
return result;
}
```

257. 二叉树的所有路径

/*
题意:输出二叉树所有路径
分析:经典递归回溯法
*/
```
vector<vector<int> >allPath; //所有路径
vector<int> aPath; //单条路径
// 经典递归回溯法求二叉树所有路径
void findPath(TreeNode* root) {
if(!root) return ;
if(!root->left && !root->right) { //leaf node
aPath.push_back(root->val);
allPath.push_back(aPath); // a path
aPath.pop_back();
return ;
}
aPath.push_back(root->val);
findPath(root->left);
findPath(root->right);
aPath.pop_back();
} vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
if(!root) return res;
findPath(root);
int len = allPath.size();
string tmpS = "";
for (int i=; i<len; i++) {
tmpS = std::to_string(allPath[i][]);
for (int j=; j<allPath[i].size(); j++) { //形成路径字符串
tmpS += ("->" + std::to_string(allPath[i][j]));
}
res.push_back(tmpS);
}
return res;
}
```

leetcode 刷题日志 2018-3-28的更多相关文章

  1. leetcode 刷题日志 2018-03-26

    58. 最后一个单词的长度 分析:找最后一个非空格,向前找 int lengthOfLastWord(string s) { int i = s.find_last_not_of(' '); int ...

  2. C#LeetCode刷题-设计

    设计篇 # 题名 刷题 通过率 难度 146 LRU缓存机制   33.1% 困难 155 最小栈 C#LeetCode刷题之#155-最小栈(Min Stack) 44.9% 简单 173 二叉搜索 ...

  3. C#LeetCode刷题-树

    树篇 # 题名 刷题 通过率 难度 94 二叉树的中序遍历   61.6% 中等 95 不同的二叉搜索树 II   43.4% 中等 96 不同的二叉搜索树   51.6% 中等 98 验证二叉搜索树 ...

  4. C#LeetCode刷题-排序

    排序篇 # 题名 刷题 通过率 难度 56 合并区间   31.2% 中等 57 插入区间   30.4% 困难 75 颜色分类   48.6% 中等 147 对链表进行插入排序   50.7% 中等 ...

  5. C#LeetCode刷题-贪心算法

    贪心算法篇 # 题名 刷题 通过率 难度 44 通配符匹配   17.8% 困难 45 跳跃游戏 II   25.5% 困难 55 跳跃游戏   30.6% 中等 122 买卖股票的最佳时机 II C ...

  6. C#LeetCode刷题-动态规划

    动态规划篇 # 题名 刷题 通过率 难度 5 最长回文子串   22.4% 中等 10 正则表达式匹配   18.8% 困难 32 最长有效括号   23.3% 困难 44 通配符匹配   17.7% ...

  7. C#LeetCode刷题-二分查找​​​​​​​

    二分查找篇 # 题名 刷题 通过率 难度 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组的中位数(Median of Two Sorted Arrays)-该题未达最优解 30 ...

  8. C#LeetCode刷题-字符串

    字符串篇 # 题名 刷题 通过率 难度 3 无重复字符的最长子串   24.6% 中等 5 最长回文子串   22.4% 中等 6 Z字形变换   35.8% 中等 8 字符串转整数 (atoi)   ...

  9. C#LeetCode刷题-双指针

    双指针篇 # 题名 刷题 通过率 难度 3 无重复字符的最长子串   24.5% 中等 11 盛最多水的容器   43.5% 中等 15 三数之和   16.1% 中等 16 最接近的三数之和   3 ...

随机推荐

  1. [C++] OOP - Access Control and Class Scope

    Access Control And Inheritance Protected Member Like private, protected members are unaccessible to ...

  2. Python面向对象-访问限制

    在Class内部,可以有字段,方法和属性,而外部代码可以通过直接调用实例变量的方法来操作数据, (1)私有普通字段 比如对于下面的Student类,name字段可以在外面通过对象进行直接访问: cla ...

  3. 软件工程课堂作业(十一)——NABC分析

    一.团队开发项目:基于Android的重力感应的解锁APP 二.项目特点:区别于一般解锁软件用开机按钮开锁解锁,我们的重力解锁软件根据动作实现解锁,减少了开机按钮的使用频率,提高寿命. 三.NABC分 ...

  4. Java容器之Iterator接口

    Iterator 接口: 1. 所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象. 2. Iterator 对象称作迭代器,用以方便的 ...

  5. java — 排序算法

    1.冒泡排序 比较相邻元素,如果第一个比第二个大,就交换位置,每一次交换,当前 package BubbleSort; public class Test { public static void m ...

  6. java — 值传递和引用传递

    在 Java 应用程序中永远不会传递对象,而只传递对象引用.因此是按引用传递对象.Java 应用程序按引用传递对象这一事实并不意味着 Java 应用程序按引用传递参数.参数可以是对象引用,而 Java ...

  7. 【Linux】- ps 命令

    Linux ps命令用于显示当前进程 (process) 的状态. 语法 ps [options] [--help] 参数: -A     列出所有的行程 -w    显示加宽可以显示较多的资讯 -a ...

  8. C#添加本地打印机

    class Program { static void Main(string[] args) { const string printerName = "Print to file&quo ...

  9. java 基础--继承--007

    1,子类只能继承父类所有非私有成员 2,子类不能继承父类的构造方法,但可以通过super去访问父类构造方法 3,子类成员变量和父类成员变量名称不一样,如果一样类似于重写,按子类处理,如果一样,就近原则 ...

  10. InnoDB实现MVCC原理

    ​ MVCC(Multi-Version Concurrent Control),即多版本并发控制,通过保存数据在某个时间点的快照来实现,因此每个读操作都会看到一个一致性的视图,并且可以实现非阻塞的读 ...