代码随想录算法训练营第十五天| 二叉树层序遍历、226.翻转二叉树、101. 对称二叉树

二叉树层序遍历

如果说前序和后序遍历是所谓的深度优先遍历,那么层序遍历便是广度优先遍历了。使用的是队列而不是栈。而如果要使用递归的话需要记录当前回溯节点的深度。

102.二叉树的层序遍历

https://leetcode.cn/problems/binary-tree-level-order-traversal/

递归

class Solution {
public:
	vector<vector<int>> levelOrder(TreeNode* root) {
		vector<vector<int>> result;
		queue<TreeNode*> que;
		if (root) que.push(root);
		int len;
		while (!que.empty()) {
			len = que.size();
			vector<int> tmp;
			for (int i = 0; i < len; i++) {
				tmp.push_back(que.front()->val);
				if (que.front()->left) que.push(que.front()->left);
				if (que.front()->right) que.push(que.front()->right);
				que.pop();
			}
			result.push_back(tmp);
		}
		return result;
	}
};

迭代

class Solution {
public:
	vector<vector<int>> levelOrder(TreeNode* root) {
		vector<vector<int>> result;
		queue<TreeNode*> que;
		if (root) que.push(root);
		int len;
		while (!que.empty()) {
			len = que.size();
			vector<int> tmp;
			for (int i = 0; i < len; i++) {
				tmp.push_back(que.front()->val);
				if (que.front()->left) que.push(que.front()->left);
				if (que.front()->right) que.push(que.front()->right);
				que.pop();
			}
			result.push_back(tmp);
		}
		return result;
	}
};

107.二叉树的层次遍历 II

https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/

从最底层子叶节点遍历到根节点,只需要将遍历结果翻转即可。

递归

class Solution {
public:
	void order2(TreeNode* cur, vector<vector<int>>& result, int depth) {
		if (!cur) return;
		if (result.size() == depth) result.push_back(vector<int>{});
		result[depth].push_back(cur->val);
		if (cur->left) order2(cur->left, result, depth + 1);
		if (cur->right) order2(cur->right, result, depth + 1);
	}
	vector<vector<int>> levelOrderBottom(TreeNode* root) {
		vector<vector<int>> result;
		order2(root, result, 0);
		reverse(result.begin(), result.end());
		return result;
	}
};

199.二叉树的右视图

https://leetcode.cn/problems/binary-tree-right-side-view/

层序遍历时只记录最右节点即可。

(采用从右遍历到左的做法,这样只要记录每一层的第一个节点就是最右节点)

递归

class Solution {
public:
	void righSide(TreeNode* cur, vector<int>& result, int depth) {
		if (!cur) return;
		if (result.size() == depth) result.push_back(cur->val);
		if (cur->right) righSide(cur->right, result, depth + 1);
		if (cur->left) righSide(cur->left, result, depth + 1);
	}
	vector<int> rightSideView(TreeNode* root) {
		vector<int> result;
		righSide(root, result, 0);
		return result;
	}
};

迭代

class Solution {
public:
	vector<int> rightSideView(TreeNode* root) {
		vector<int> result;
		queue<TreeNode*> que;
		if (root) que.push(root);
		while (!que.empty()) {
			result.push_back(que.front()->val);
			int len = que.size();
			while (len--) {
				if (que.front()->right) que.push(que.front()->right);
				if (que.front()->left) que.push(que.front()->left);
				que.pop();
			}
		}
		return result;
	}
};

637.二叉树的层平均值

https://leetcode.cn/problems/average-of-levels-in-binary-tree/

在层序遍历时用一个vector<pair<double, int>>容器来记录每一层的元素之和和元素数量。

递归

class Solution {
public:
	void averLev(TreeNode* cur, vector<pair<double, int>> &dat, int depth) {
		if (!cur) return;
		if (dat.size() == depth) dat.push_back(pair<int, int> {cur->val, 1});
		else {
			dat[depth].first += (double)cur->val;
			dat[depth].second++;
		}
		averLev(cur->left, dat, depth + 1);
		averLev(cur->right, dat, depth + 1);
	}
	vector<double> averageOfLevels(TreeNode* root) {
		vector<pair<double, int>> dat;
		vector<double> result;
		averLev(root, dat, 0);
		for (auto iter : dat) {
			result.push_back(iter.first / iter.second);
		}
		return result;
	}
};

429.N叉树的层序遍历

https://leetcode.cn/problems/n-ary-tree-level-order-traversal/

和普通的层序遍历差不多,将原本的两步left和right改为for循环

递归

class Solution {
public:
    void oderN(Node* cur, vector<vector<int>> &result, int depth){
        if(!cur) return;
        if(result.size() == depth) result.push_back(vector<int>{});
        result[depth].push_back(cur->val);
        for(int i = 0; i < cur->children.size(); i++){
            oderN(cur->children[i], result, depth + 1);
        }
    }
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> result;
        oderN(root, result, 0);
        return result;
    }
};

515.在每个树行中找最大值

https://leetcode.cn/problems/find-largest-value-in-each-tree-row/

层序遍历时给每一层记录一个最大值,然后用每一个遍历的元素去比较该层的最大值即可。

迭代

class Solution {
public:
	vector<int> largestValues(TreeNode* root) {
		vector<int> result;
		queue<TreeNode*> que;
		if (root) que.push(root);
		while (!que.empty()) {
			int len = que.size();
			int tmp = que.front()->val;
			while (len--) {
				tmp = tmp >= que.front()->val ? tmp : que.front()->val;
				if(que.front()->left)que.push(que.front()->left);
				if(que.front()->right)que.push(que.front()->right);
				que.pop();
			}
			result.push_back(tmp);
		}
		return result;
	}
};

116.填充每个节点的下一个右侧节点指针

https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/

本题和下一题使用的相同的代码

117.填充每个节点的下一个右侧节点指针II

https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/

正常层序遍历即可,将每一层元素的next接入该层下一个元素,如果没有就介入nullptr

递归

class Solution {
public:
    void con(Node* cur, vector<Node*> &last, int depth){
        if(!cur) return;
        if(last.size() == depth){
            last.push_back(cur);
            cur->next = nullptr;
        }
        else{
            last[depth]->next = cur;
            last[depth] = cur;
            cur->next = nullptr;
        }
        con(cur->left, last, depth + 1);
        con(cur->right, last, depth + 1);
    }
    Node* connect(Node* root) {
        vector<Node*> last;
        con(root, last, 0);
        return root;
    }
};

迭代

class Solution {
public:
    Node* connect(Node* root) {
        Node* cur;
        queue<Node*> que;
        if(root) que.push(root);
        while(!que.empty()){
            int len = que.size();
            while(len--){
                cur = que.front();
                que.pop();
                if(len) cur->next = que.front();
                else cur->next = nullptr;
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
        } 
        return root;
    }
};

104.二叉树的最大深度

https://leetcode.cn/problems/maximum-depth-of-binary-tree/

一路层序遍历到尾,记录最后一个元素的深度即可。

递归(最后result++的原因是设置的根节点深度是从0开始,而最终结果要求是从1开始)

class Solution {
public:
    void maxD(TreeNode * cur, int & max, int depth){
        if(!cur) return;
        max = max > depth ? max : depth;
        if(cur->left) maxD(cur->left, max, depth + 1);
        if(cur->right) maxD(cur->right, max, depth + 1);
    }
    int maxDepth(TreeNode* root) {
        if(!root) return 0;
        int result = 0;
        maxD(root, result, 0);
        result++;
        return result;
    }
};

迭代

class Solution {
public:
    int maxDepth(TreeNode* root) {
        int result = 0;
        queue<TreeNode*> que;
        if(root) que.push(root);
        while(!que.empty()){
            result++;
            int len = que.size();
            while(len--){
                if(que.front()->left) que.push(que.front()->left);
                if(que.front()->right) que.push(que.front()->right);
                que.pop();
            }
        }
        return result;
    }
};

111.二叉树的最小深度

https://leetcode.cn/problems/minimum-depth-of-binary-tree/

递归(在每一次遍历的时候寻找有没有left和right均为nullptr的节点,记录其深度,和当前记录的最小深度进行比较,最终得到一个最小深度。)

class Solution {
public:
    void minD(TreeNode* cur, int &min, int depth){
        if(!cur) return;
        if(!cur->left && !cur->right){
            if(!min) min = depth;
            else min = min < depth ? min : depth;
        }
        if(cur->left) minD(cur->left, min, depth + 1);
        if(cur->right) minD(cur->right, min, depth + 1);
    }
    int minDepth(TreeNode* root) {
        if(!root) return 0;
        int result = 0;
        minD(root, result, 0);
        result++;
        return result;
    }
};

迭代(因为队列的特性,只要找到第一个左节点和右节点均为nullptr的节点就可以返回了)

class Solution {
public:
    int minDepth(TreeNode* root) {
        int result = 0;
        queue<TreeNode*> que;
        if(root) que.push(root);
        while(!que.empty()){
            int len = que.size();
            result++;
            while(len--){
                if(!que.front()->left && !que.front()->right){
                    return result;
                }
                if(que.front()->left) que.push(que.front()->left);
                if(que.front()->right) que.push(que.front()->right);
                que.pop();
            }
        }
        return result;
    }
};

226.翻转二叉树

https://leetcode.cn/problems/invert-binary-tree/

可以使用前序和后序,不能用中序,否则会有一部分节点翻转两次,一部分节点不翻转

递归

class Solution {
public:
    void invert(TreeNode* cur){
        if(!cur) return;
        TreeNode* tmp = cur->left;
        cur->left = cur->right;
        cur->right = tmp;
        invert(cur->left);
        invert(cur->right);
    }
    TreeNode* invertTree(TreeNode* root) {
        invert(root);
        return root;
    }
};

迭代(这里cur既用于存储从栈中弹出的节点用用于做交换用的临时节点,可能不直观)

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> stk;
        if(root) stk.push(root);
        while(!stk.empty()){
            TreeNode* cur = stk.top()->left;
            stk.top()->left = stk.top()->right;
            stk.top()->right = cur;
            cur = stk.top();
            stk.pop();
            if(cur->left) stk.push(cur->left);
            if(cur->right) stk.push(cur->right);
        }
        return root;
    }
};

101. 对称二叉树

https://leetcode.cn/problems/symmetric-tree/

分别以root的left和right节点作为根节点遍历二叉树,遍历方式不限,只要遍历左右顺序相反(比如一个左一个右),只要出现有不同的情况就可以返回false了

递归

class Solution {
public:
    bool myCmp(TreeNode* left, TreeNode* right){
        if(!left && !right) return true;
        if(!(left && right)) return false;
        if(left->val != right->val) return false;
        return (myCmp(left->left, right->right) && myCmp(left->right, right->left));
    }
    bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        return myCmp(root->left, root->right);
    }
};

迭代

用一个队列

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        queue<TreeNode*> que;
        que.push(root->left);
        que.push(root->right);
        while(!que.empty()){
            TreeNode* ptr1 = que.front();
            que.pop();
            TreeNode* ptr2 = que.front();
            que.pop();
            if(!ptr1 && !ptr2) continue;
            if(!(ptr1 && ptr2)) return false;
            if(ptr1->val != ptr2->val) return false;
            que.push(ptr1->right);
            que.push(ptr2->left);
            que.push(ptr1->left);
            que.push(ptr2->right);
        }
        return true;
    }
};

 用两个栈(其实一个栈也可以)

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        stack<TreeNode*> stk1, stk2;
        stk1.push(root->left);
        stk2.push(root->right);
        while(!stk1.empty() && !stk2.empty()){
            TreeNode* ptr1 = stk1.top();
            TreeNode* ptr2 = stk2.top();
            stk1.pop();
            stk2.pop();
            if(!ptr1 && !ptr2) continue;
            if(!(ptr1 && ptr2)) return false;
            if(ptr1->val != ptr2->val) return false;
            stk1.push(ptr1->right);
            stk1.push(ptr1->left);
            stk2.push(ptr2->left);
            stk2.push(ptr2->right);
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值