剑offer - 1 - 二叉树

这篇博客主要介绍了关于二叉树的一系列算法题目,包括LC958的完全性校验、蛇形遍历、重建二叉树、判断子结构、对称二叉树、从上到下打印、二叉搜索树的后序遍历序列、求和路径、最近祖先、删除节点以及计算二叉树深度等。通过这些题目,博主探讨了不同类型的二叉树问题及其解题思路。
摘要由CSDN通过智能技术生成
LC958二叉树的完全性校验

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isCompleteTree(TreeNode* root) {
        if(root == nullptr) return true;
        bool flag = false;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty()){
            TreeNode *t = q.front();q.pop();
            if(t == nullptr){
                flag = true;
                continue;
            }
            if(flag) return false; 
            //走到这个if说明此次循环没有t!=nullptr,而上次循环t==nullptr,
            //所以说明有空节点夹杂在非空结点之前。
            q.push(t->left);
            q.push(t->right);
        }
        return true;
    }
};
103.蛇形二叉树遍历

算法题:给定一棵二叉树,返回蛇形遍历顺序。leetcode水题,宽度优先遍历之后将偶数行的结果reverse就可以。只做出这一个。
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;

struct TreeNode{
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x): val(x), left(NULL), right(NULL){};
};

TreeNode* init(int *a, int len){
	TreeNode *root = nullptr;
	TreeNode *p = nullptr;
	int flag = 0;
	for(int i=0;i<len;){
		if(i == 0)  {
				root = new TreeNode(a[i++]);
				p = root;
				cout<<p->val<<"mmm"<<endl;
		}else{
				cout<<a[i]<<"mmm"<<endl;
				if(a[i] == NULL) p->left=nullptr;
				else p->left = new TreeNode(a[i]);
				i++;
				cout<<a[i]<<"mmm"<<endl;
				if(a[i] == NULL) p->right=nullptr;
				else p->right = new TreeNode(a[i]);
				i++;
				if(flag == 0) {
						if(p->left) p = p->left;
						flag=1;
				}else if(flag == 1){
					if(p->right) p = p->right;
					flag = 0;
				}
		}
	}
	return root;
}


void levelOrder(TreeNode *root){
	TreeNode *p = root;
	queue<TreeNode*> q;
	q.push(root);
	vector<vector<int>> v;
	int level = 1;
	while(!q.empty()){
		int size = q.size();
		vector<int>t;
		for(int i=0;i<size;i++){
			p = q.front();q.pop();
			t.push_back(p->val);
			if(p->left) q.push(p->left);
			if(p->right) q.push(p->right);
		}
		if(level %2 == 0) reverse(t.begin(),t.end());
		v.push_back(t);
		level++;
	}
	for(int i=0;i<v.size();i++){
		for(vector<int>::iterator it = v[i].begin(); it != v[i].end(); it++){
			cout<<*it<<",";
		}
		cout<<endl;
	}
}

int main(){
	int a[] = {3,9,20,NULL,NULL,15,7};
	int len = sizeof(a)/sizeof(a[0]);
	TreeNode *root = init(a, len);
	levelOrder(root);

}

00.二叉树遍历

#include<bits/stdc++.h>

using namespace std;

struct TreeNode{
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x):val(x),left(NULL),right(NULL){}
};

void PreOrder(TreeNode *root){
	if(root == NULL) return ;
	TreeNode *p = root;
	cout<<p->val<<" ";
	PreOrder(p->left);
	PreOrder(p->right);
}

//层序非递归是一个队列
//前序非递归是一个栈
void PreOrder2(TreeNode *root){
	if(root == NULL) return;
	TreeNode *p = root;
	stack<TreeNode *>s;
	while(p || !s.empty()){
		while(p){
			cout<<p->val<<" ";
			s.push(p);
			p = p->left;
		}
		if(!s.empty()){
			p = s.top(); s.pop();
			p = p->right;
		}

	}

}
void InOrder(TreeNode *root){
	if(root == NULL) return ;
	InOrder(root->left);
	cout<<root->val<<" ";
	InOrder(root->right);
}

void InOrder2(TreeNode *root){
	if(root == NULL) return;
	TreeNode *p = root;
	stack<TreeNode *> s;
	while(p || !s.empty()){
		while(p){
			s.push(p);
			p = p->left;
		}
		if(!s.empty()){
			p = s.top();
			s.pop();
			cout<<p->val<<" ";
			p = p->right;

		}
	}
}

void PostOrder(TreeNode *root){
	if(root == NULL) return ;
	PostOrder(root->left);
	PostOrder(root->right);
	cout<<root->val<<" ";
}


void postorder(TreeNode *root) {
	stack<TreeNode*> s;
	TreeNode* pre=NULL;
	TreeNode* cur;
	s.push(root);
	while(!s.empty()) {
		cur = s.top();
		if ((cur->left==NULL && cur->right==NULL) ||
			(pre!=NULL&&(pre==cur->left||pre==cur->right))) {
				cout << cur->val << " ";
				pre = cur;
				s.pop();
			}
		if (cur->right) s.push(cur->right);
		if (cur->left) s.push(cur->left);
	}
}

//后序遍历非递归1:由前序非递归改进,采用根右左的遍历写法,最后结果再翻转
void PostOrder1(TreeNode *root){
	vector<TreeNode*> v;
	stack<TreeNode*>s;
	TreeNode *p = root;
	while(p || !s.empty()){
		while(p){
			v.push_back(p);
			s.push(p);
			p=p->right;
		}
		if(!s.empty()){
			p = s.top();s.pop();
			p = p->left;
		}
	}
	reverse(v.begin(),v.end());
	for(int i=0;i<v.size();i++){
		cout<<v[i]->val<<" ";
	}
}

//后序遍历非递归2:建立一个指向前一节点的指针,标记右孩子是否被访问
void PostOrder2(TreeNode *root){
	TreeNode *pre = NULL;
	TreeNode *p = root;
	stack<TreeNode*>s;
	while(p || !s.empty()){
		while(p){
			s.push(p);
			p = p->left;
		}
		p = s.top();//这里先不要弹出栈顶,因为可能右子树还要进来,如果有右子树要进来则这个相对根节点就需要稍后再弹出
		if(p->right == pre || p->right == NULL){ //若没有右节点或者右节点已经被访问过则输出这个相对根节点
			s.pop();
			cout<<p->val<<" ";
			pre = p;
			p = NULL;
		}else{
			p = p->right;
		}
	}
}

void LevelOrder(TreeNode *root){
	queue<TreeNode*> q;
	q.push(root);
	TreeNode *p = root;
	while(!q.empty()){
		p = q.front();
		q.pop();
		cout<<p->val<<" ";
		if(p->left) q.push(p->left);
		if(p->right) q.push(p->right);
	}
}

TreeNode* init(TreeNode *root){
	TreeNode *p = root;
	fstream f("int.txt");
	int x;
	while(f>>x){
		if(p->left == NULL){
			p->left = new TreeNode(x);
		}else{
			p->right = new TreeNode(x);
			p = p->left;

		}
	}
	return root;
}


int main(){
	TreeNode root(0);
	init(&root);
	cout<<"前序:"<<" ";
	PreOrder(&root);
	cout<<"\n前序:"<<" ";
	PreOrder2(&root);
	cout<<"\n中序: " <<" ";
	InOrder(&root);
	cout<<"\n中序: " <<" ";
	InOrder2(&root);
	cout<<"\n后序: " <<" ";
	PostOrder(&root);
	cout<<endl;
	PostOrder1(&root);
	cout<<endl;
	PostOrder2(&root);
	cout<<"\n层序:"<<" ";
	LevelOrder(&root);
}

	//				0
	//			1		2
	//		3		4
	//	5		6
	//7		8
//9

07.重建二叉树(给前中写后序)

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7
/**
 * 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:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        //递归分治
        return recursionBuild(preorder.begin(),preorder.end(),inorder.begin(),inorder.end());
    }

    //递归分治
    TreeNode* recursionBuild(vector<int>::iterator preBegin, vector<int>::iterator preEnd,vector<int>::iterator inBegin, vector<int>::iterator inEnd )
    {
        if(inEnd==inBegin) return NULL;
        TreeNode* cur = new TreeNode(*preBegin);
        auto root = find(inBegin,inEnd,*preBegin);
        cur->left = recursionBuild(preBegin+1,preBegin+1+(root-inBegin),inBegin,root);
        cur->right = recursionBuild(preBegin+1+(root-inBegin),preEnd,root+1,inEnd);
        return cur;
    }
};

感想:迭代器迭代器迭代器

26.树的子结构

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。

/**
 * 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 isSubStructure(TreeNode* A, TreeNode* B) {
        if(A==NULL|| B==NULL) return false;
        bool res = false;
        if(A->val == B->val){
            res = helper(A,B);
        }
        if(!res){
            res = isSubStructure(A->left,B);
        }
        if(!res){
            res = isSubStructure(A->right,B);
        }
        return res;
    }
    
    bool helper(TreeNode* a,TreeNode* b){
        if(b==NULL) return true;
        if(a==NULL) return false;
        if(a->val == b->val) return helper(a->left,b->left) && helper(a->right,b->right);
        else return false;
    }
};

感想:递归敢于截止。

28. 对称的二叉树

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root == NULL) return true;
        else  return helper(root->left,root->right);
    }

    bool helper(TreeNode* leftRoot,TreeNode* rightRoot){
        if(leftRoot == NULL && rightRoot == NULL) return true;
        else if(leftRoot == NULL || rightRoot == NULL) return false;
        if(leftRoot->val != rightRoot->val) return false;
        else return helper(leftRoot->left,rightRoot->right) && helper(leftRoot->right,rightRoot->left);
    }
};

32-3 从上到下打印二叉树

class Solution {
public:
    vector<vector<int>> v;
    vector<vector<int>> levelOrder(TreeNode* root) {
        dfs(root,0);
        return v;
    }

    void dfs(TreeNode* root,int level){
        if(root == NULL) return ;
        if(level>=v.size()) v.emplace_back(vector<int>());
        v[level].emplace_back(root->val);
        if(root->left) dfs(root->left,level+1);
        if(root->right) dfs(root->right,level+1);
    }
};

33.二叉搜索树树后序遍历序列

在这里插入图片描述

bool fun2(vector<int> &a,int left,int right){
	if(left >= right) return true;
	int pos = left;
	for(;pos<right;pos++){
		if(a[pos]>a[right]) break;
	}
	for(int j=pos;j<right;j++){
		if(a[j]<a[right]) return false;
	}
	return fun2(a,left,pos-1) && fun2(a,pos,right-1);
}

void fun1(vector<int> &a){
	fun2(a,0,a.size()-1);	
} 

34.二叉树中和为某一值的路径

输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。

 

示例:
给定如下二叉树,以及目标和 sum = 22,

              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1

返回:

[
   [5,4,11,2],
   [5,8,4,5]
]
class Solution {
public:
    vector<vector<int>> v;
    vector<int> single;
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        if(root == NULL) return v;
        dfs(root,sum);
        return v;
    }

    void dfs(TreeNode* root,int sum){
        if(root == NULL) return;
        sum -= root->val;
        single.push_back(root->val);
        if(!root->left && !root->right && sum == 0) v.emplace_back(single);
        dfs(root->left,sum);
        dfs(root->right,sum);
        single.pop_back();
    }
};

感想:想成了每次怎么新建一个vector实际上每一条dfs深度里都是一条新的vector,即使用的全局变量。

68-1 二叉搜索树中的最近祖先

在这里插入图片描述

/**
 * 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:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root->val < p->val && root->val < q->val) return lowestCommonAncestor(root->right, p, q);
        if(root->val > p->val && root->val > q->val) return lowestCommonAncestor(root->left, p, q);
        return root;
    }
};
//迭代
class Solution {
    public:
    TreeNode* lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q) {
        while(root != NULL) {
            if(root->val < p->val && root->val < q->val) // p,q 都在 root 的右子树中
                root = root->right; // 遍历至右子节点
            else if(root->val > p->val && root->val > q->val) // p,q 都在 root 的左子树中
                root = root->left; // 遍历至左子节点
            else break;
        }
        return root;
    }
};

68-2二叉树中的最近公共祖先

在这里插入图片描述

TreeNode* fun1(TreeNode *root,TreeNode *p,TreeNode *q){
	if(root == NULL) return NULL;
	if(root->val == p->val || root->val == q->val) return root;
	TreeNode *left = fun1(root->left,p,q);
	TreeNode *right = fun1(root->right,p,q);
	if(left == NULL && right == NULL) return NULL;
	if(left == NULL) return right;
	if(right == NULL) return left;
	return root;
}

18.删除指定节点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
        ListNode* p = head;
        ListNode* q = p;
        if(p->val == val){
            head = head->next;
            return head;
        }
        while(p->next){
            q=p;
            p=p->next;
            if(p->val == val){
                if(p->next) q->next = p->next;
                else q->next = NULL;
                break;
            }
        }
        return head;
    }
};

55.二叉树深度

/**************************BFS*************************/

class Solution {
public:
    int length=0;
    queue<TreeNode*> q;
    int maxDepth(TreeNode* root) {
       if(root == NULL) return 0;
       q.push(root);
       while(!q.empty()){
           int size = q.size();
           for(int i=0;i<size;i++){
               TreeNode* tmp = q.front();q.pop(); 
    //注意这个出队操作是写在横排for的里面的,就是说同一行的节点的出队操作值归为length加一次。
               if(tmp->left) q.push(tmp->left);
               if(tmp->right) q.push(tmp->right);
           }
           length+=1;
       }
       return length;
    }
};

/****************DFS**************************/
class Solution {
public:
    int maxDepth(TreeNode* root) {
	    if(root == NULL) return 0;
	    return max(maxDepth(root->left),maxDepth(root->right))+1;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值