Leetcode学习之二叉树与图(2)

开宗明义:本系列基于小象学院林沐老师课程《面试算法 LeetCode 刷题班》,刷题小白,旨在理解和交流,重在记录,望各位大牛指点!


Leetcode学习之二叉树与图(2)



1、二叉树转链表 Leetcode 114.

题目来源: L e e t c o d e   114.   F l a t t e n   B i n a r y   T r e e   t o   L i n k e d   L i s t Leetcode \ 114. \ Flatten \ Binary \ Tree \ to \ Linked \ List Leetcode 114. Flatten Binary Tree to Linked List
题目描述给定一个二叉树,将该二叉树就地(in-place)转换为单链表。单链表中节点顺序为二叉树前序遍历顺序
要求描述
在这里插入图片描述

1.1 方法一

分析
在这里插入图片描述

测试代码:

#include <stdio.h>
#include <vector>
using namespace std;

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

class Solution {
public:
	void flatten(TreeNode *root) {
		vector<TreeNode*> node_vec;
		preorder(root, node_vec);
		for (int i = 1; i < node_vec.size(); i++) {
			node_vec[i - 1]->left = NULL;
			node_vec[i - 1]->right = node_vec[i];
		}
	}
private:
	void preorder(TreeNode *node, vector<TreeNode *> &node_vec) {
		if (!node) {
			return;
		}
		node_vec.push_back(node);
		preorder(node->left, node_vec);
		preorder(node->right, node_vec);
	}
};

int main() {
	TreeNode a(1), b(2), c(5), d(3), e(4), f(6);
	a.left = &b;
	a.right = &c;
	b.left = &d;
	b.right = &e;
	c.right = &f;
	Solution solve;
	solve.flatten(&a);
	TreeNode *head = &a;
	while (head)
	{
		if (head->left) {
			printf("error!\n");
		}
		printf("[%d]", head->val);
		head = head->right;
	}
	printf("\n");
	system("pause");
	return 0;
}

效果图
在这里插入图片描述


1.2 方法二

分析
在这里插入图片描述
测试代码:

#include <stdio.h>
#include <vector>
using namespace std;

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

class Solution {
public:
	void flatten(TreeNode *root) {
		TreeNode *last = NULL;//末尾节点
		preorder(root, last);
	}
private:
	void preorder(TreeNode *node, TreeNode *&last) {
		if (!node) {//为空返回
			return;
		}
		if (!node->left && !node->right) {//这个节点没有左右子树,为最终的叶节点
			last = node;
			return;
		}
		TreeNode *left = node->left;//备份左右指针
		TreeNode *right = node->right;
		TreeNode *left_last = NULL;//左右子树的最后一个节点
		TreeNode *right_last = NULL;

		if (left) {
			preorder(left, left_last);//若有左子树,递归将左子树变成单链表
			node->left = NULL;
			node->right = left;
			last = left_last;//将该节点的last保存为左子树的last
		}

		if (right) {//若有右子树,递归将右子树转化为单链表
			preorder(right, right_last);//若node找到左子树的最后一个节点(有左子树)
			if (left_last) {
				left_last->right = right;
			}
			last = right_last;
		}
	}
};

int main() {
	TreeNode a(1), b(2), c(5), d(3), e(4), f(6);
	a.left = &b;
	a.right = &c;
	b.left = &d;
	b.right = &e;
	c.right = &f;
	Solution solve;
	solve.flatten(&a);
	TreeNode *head = &a;
	while (head)
	{
		if (head->left) {
			printf("error!\n");
		}
		printf("[%d]", head->val);
		head = head->right;
	}
	printf("\n");
	system("pause");
	return 0;
}

效果图
在这里插入图片描述


2、二叉树层次遍历

描述二叉树层次遍历,又称宽度优先搜索,按树的层次依次访问树的结点。层次遍历使用队列对遍历节点进行存储,先进入队列的结点,优先遍历拓展其左孩子与右孩子
分析
在这里插入图片描述
在这里插入图片描述
测试代码:

#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;

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

void DFS_print(TreeNode* root) {//宽度优先搜索二叉树
	queue<TreeNode *> Q;
	Q.push(root);
	while (!Q.empty())
	{
		TreeNode *node = Q.front();
		Q.pop();
		printf("[%d]\n", node->val);
		if (node->left) {
			Q.push(node->left);
		}
		if (node->right) {
			Q.push(node->right);
		}
	}
}

int main() {
	TreeNode a(1), b(2), c(5), d(3), e(4), f(6);
	a.left = &b;
	a.right = &c;
	b.left = &d;
	b.right = &e;
	c.right = &f;
	DFS_print(&a);
	system("pause");
	return 0;
}

效果图
在这里插入图片描述

3、侧面观察二叉树(二叉树宽搜) Leetcode 199.

题目来源: L e e t c o d e   199.   B i n a r y   T r e e   R i g h t   S i d e   V i e w Leetcode \ 199. \ Binary \ Tree \ Right \ Side \ View Leetcode 199. Binary Tree Right Side View
题目描述给定一个二叉树,假设从该二叉树的右侧观察它,将观察到的节点按照从上到下的顺序输出
要求描述
在这里插入图片描述
分析
在这里插入图片描述
在这里插入图片描述

测试代码:

#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;

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

class Solution {
public:
	vector<int> rightSideView(TreeNode *root) {
		vector<int> view;//按层遍历的最后一个节点
		queue<pair<TreeNode*, int>> Q;
		//宽度优先搜索队列<节点,层数>
		if (root) {//根节点非空时,将<root,0>push进入队列
			Q.push(make_pair(root, 0));
		}

		while (!Q.empty())
		{
			TreeNode *node = Q.front().first;//搜索节点
			int depth = Q.front().second;//待搜索节点的层数
			Q.pop();

			if (view.size() == depth) {
				view.push_back(node->val);//第一个赋初值
			}
			else
			{
				view[depth] = node->val;//更新
			}

			if (node->left) {
				Q.push(make_pair(node->left, depth + 1));
			}

			if (node->right) {
				Q.push(make_pair(node->right, depth + 1));
			}
		}
		return view;
	}
};

int main() {
	TreeNode a(1), b(2), c(5), d(3), e(4), f(6);
	a.left = &b;
	a.right = &c;
	b.left = &d;
	b.right = &e;
	c.right = &f;
	Solution solve;
	vector<int> result = solve.rightSideView(&a);
	for (int i = 0; i < result.size(); i++) {
		printf("[%d]\n", result[i]);//结果vector
	}
	system("pause");
	return 0;
}

效果图
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值