【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】

【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】

  • Day8 04-07 LeetCode探索:二叉树的典型操作实现【递归思想】
    • 1.今日感想
    • 2.计划执行报告
      • 2.1近期计划(03-31-04-12)
      • 2.2今日计划表
      • 2.3实际时间分配
    • 3. 二叉树的结构构造与常用操作实现
    • 4. LeetCode探索:二叉树的典型操作实现
      • 4.1 实现过程中遇到的ERROR
      • 4.2 Leetcode探索闯关题解记录
    • 【明日计划】

Day8 04-07 LeetCode探索:二叉树的典型操作实现【递归思想】

今天是:

  1. 计划执行的第8
  2. 学习二叉树的一天
  3. 从计划实现开始“浪”的时间最多的一天

从今天开始,非特殊情况不会把写这些报告的时间记录在atimelogger中(因为写报告时时间的记录已经停止了),并且准备把明日的计划也贴在最后

1.今日感想

  1. 机器学习的VAE听不进去;
  2. 通过之前的学习以及今天的编程实践对二叉树的性质、典型操作(递归实现如DFS遍历、BFS遍历等等)有了更深刻的理解,但是目前还没尝试过用迭代方法解决这些问题;
  3. 掌握这些典型数据结构不仅仅是为了程序竞赛,更重要地是它们作为一些机器学习算法的先修内容,有助于机器学习相关算法的理解,如决策树、isomap等等

2.计划执行报告

2.1近期计划(03-31-04-12)

1.有所改动,貌似组内的大佬已经把所有工作承包了,而且报告日期推迟到了下周三,因此任务重心由“在4月12日之前准备好(推迟了)机器学习的最终报告——《畅想无监督学习》”变为了补充机器学习所需的数学知识(线性代数与概率统计)
2.完成专业课的作业(流体机械能转化、生物质能,新能源热利用可以往后稍稍);
3.备战蓝桥杯,为此:①1h左右的典型算法补充(优先Leetcode“探索”模块);②C/C++语法知识;③常见数据结构的构造与基本操作实现;④必要的练习与练题总结(比如时长1:30虚拟竞赛与“复盘”)

2.2今日计划表

【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第1张图片

2.3实际时间分配

  1. 今天玩嗨了,以后要注意;
  2. 至于洗漱超时,主要是今天洗了澡
【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第2张图片图1 时间分配
【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第3张图片图2 目标达成情况

3. 二叉树的结构构造与常用操作实现

今天上午自己写了个cpp程序把二叉树实现了一下,为了写起来方便没把结构定义放在头文件中,途中遇到一个低级失误:在实现完先序遍历后,准备写中序和后序遍历函数时,忘记把函数体内的递归函数的名称改了,导致结果与预期不符,我找错误用了半个小时,真的心态有点小崩。教训就是:对于递归问题,Ctrl+C/V时一定要留意内部调用的函数是否需要变化

以下是实现的cpp代码:

#include
#include
#include
using namespace std;
typedef int elem;
typedef struct TreeNode{
	elem val;
	struct TreeNode* left,*right;
}BiNode,*BiTree; 

void visit(elem val){//访问操作
	cout<<val<<endl;
}
void PreOrderTraverse(BiTree T){//先序遍历
	if(T){
		visit(T->val);
		PreOrderTraverse(T->left);
		PreOrderTraverse(T->right);		
	}
}

void PostOrderTraverse(BiTree T){//后序遍历
	if(T){
		//论复制粘贴的坏处,困扰了我半小时 
		//PreOrderTraverse(T->left);
		//PreOrderTraverse(T->right);
		PostOrderTraverse(T->left);
		PostOrderTraverse(T->right);
		visit(T->val);	
	}

}

void InOrderTraverse(BiTree T){//中序遍历
	if(T){
		//PreOrderTraverse(T->left);
		InOrderTraverse(T->left);
		visit(T->val);
		//PreOrderTraverse(T->right);	
		InOrderTraverse(T->right);
	}

}
//假定元素非负 
void CreateBiTree(BiTree *T){//树的构建
	int x;
	cin>>x;
	if(x<0) return;
	else{
		*T=(BiNode*)malloc(sizeof(BiNode));
		(*T)->val=x;
		(*T)->left=NULL;
		(*T)->right=NULL;
		CreateBiTree(&((*T)->left));//->的优先级比*高 
		CreateBiTree(&((*T)->right));
	}
}
//静态数组(假定元素不超过6个)
void LOT(BiTree T){//按层次遍历
	if(T){
		int front=-1,rear=0;
		BiTree queue[6];
		BiTree p;
		queue[0]=T;
		while(front<rear){
			p=queue[++front];
			visit(p->val);
			if(p->left)
				queue[++rear]=p->left;
			if(p->right)
				queue[++rear]=p->right;
		}
	}
	
}
//STL模板 
void LayerOrderTraverse(BiTree T){//按层次遍历
	if(T){
		queue<BiTree> q;
		BiTree p;
		q.push(T);
		while(!q.empty()){
			p=q.front();
			q.pop();
			visit(p->val);
			if(p->left)
				q.push(p->left);
			if(p->right)
				q.push(p->right);	
		}
	} 
}
int main(){
	BiTree T;
	CreateBiTree(&T); 
	cout<<"DLR"<<endl;
	PreOrderTraverse(T);
	cout<<"LRD"<<endl;
	PostOrderTraverse(T);
	cout<<"LDR"<<endl;
	InOrderTraverse(T);
	cout<<"LayerOrderTraverse:"<<endl;
	//LayerOrderTraverse(T);
	LOT(T);
	free(T);
	return 0;
} 

4. LeetCode探索:二叉树的典型操作实现

目前Leetcode二叉树部分完成了2/3,还剩下总结篇的六道算法题。做这些题的目的便是熟悉竞赛时的风格,毕竟对于同一个知识点可能在形式上会有所变化。

4.1 实现过程中遇到的ERROR

先摆上在Leetcode上调试时遇到的几个问题:

  1. 【ERROR】Vector declaration “expected parameter declarator”
    在stack-overflow上看到的一个解答如下:
    【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第4张图片
    意思是,对于容器变量的初始化,一定不要放在函数之外(可以声明,但是不能定义),这个也困扰了我很久(找时间一定要好好看看容器模板)。例如以下写法就是错误的:
    【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第5张图片
  2. 【ERROR】reference binding to null pointer of type ‘value_type’
    这个问题很有可能是数组(容器)越界了,要检查下相关的数组(容器)下标是否越界。

4.2 Leetcode探索闯关题解记录

以下是今日闯关的4道题,大多是用递归实现的,关于遍历(上午的代码已经展示过了)操作就不再列出了。部分题可以用迭代,但是暂时还不会。

Stage 01 二叉树的层序遍历
【题目描述】
【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第6张图片
这个应该令我印象最为深刻的一道题了,尽管层序遍历之前写过了,但就因为它的返回值形式使得这道题的写法大变样,要考虑层次以及容器的扩容。费了不少时间,以下是我的解法:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> v;
    vector<vector<int>> levelOrder(TreeNode* root) {
        if(root){
            queue<pair<TreeNode*,int> >q;
            TreeNode* node;
            q.push(make_pair(root,0)); //
            int cur_size=0; //v的当前数组元素个数
            while(!q.empty()){
                pair<TreeNode*,int>p=q.front();
                
                node=p.first;
                q.pop();
                if(cur_size<=p.second){
                    cur_size=p.second+1;
                    v.resize(cur_size);
                }           
                v[p.second].push_back(p.first->val);
                
                if(node->left)
                    q.push(make_pair(node->left,p.second+1));
                if(node->right)
                    q.push(make_pair(node->right,p.second+1));
                
            } 
        }
        return v;

    }
};

Stage 02 二叉树的最大深度
【题目描述】
【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第7张图片
有自顶向下(top-down)以及自底向上(bottom-up)两种方法,选取方法的原则如下,我采用的是后者。
【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第8张图片

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int ans=0;
    int max(int a,int b){
        return a>b?a:b;
    }
    int maxDepth(TreeNode* root) {
        if(!root)
            return 0;
        return max(maxDepth(root->left),maxDepth(root->right))+1;
    }
};

Stage 03 对称二叉树
【题目描述】
【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第9张图片
想了挺久的(主要是递归的方向选错了),不过看了别人的思路后很快就实现了。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSymmetric(TreeNode* nl,TreeNode* nr){
        if(!nl&&!nr)//两子树均为空
            return true;
        if(nl&&!nr||!nl&&nr)//一个为空,另一个不为空
            return false;
        if(nl->val!=nr->val)//判断两子树的节点是否相同
            return false;
        return isSymmetric(nl->left,nr->right)&
        isSymmetric(nl->right,nr->left);        
    }
    bool isSymmetric(TreeNode* root) {
        if(!root)//空树被认为是对称的
            return true;
        return isSymmetric(root->left,root->right);
    }
};

Stage 04 路径总和
【题目描述】
【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第10张图片
这个递归挺好想的,实现如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if(!root)//空树返回false
            return false;
        if(!root->left&&!root->right)//叶子节点
            return sum==root->val;
        return hasPathSum(root->left,sum-root->val)|
        hasPathSum(root->right,sum-root->val);
    }
};

回想半年前,还在旁听数据结构的时候,当时是多么地抵触”树”,现在觉得好像也就那样(当然现在实现的操作都是些皮毛啦),这也是为何“早接触一些东西总会是好的”的缘故吧!

【明日计划】

【计划执行报告】Day8 LeetCode探索:二叉树的典型操作实现【递归思想】_第11张图片

你可能感兴趣的:(计划执行报告,数据结构与算法,常见错误记录,二叉树,leetcode,经验分享)