目录
173.二叉搜索树迭代器
222.完全二叉树的节点个数
199.二叉树的右视图
637.二叉树的层平均值
102.二叉树的层序遍历
103.二叉树的锯齿形层次遍历
题意:
实现一个二叉搜索树迭代器类
BSTIterator
,表示一个按中序遍历二叉搜索树(BST)的迭代器:
BSTIterator(TreeNode root)
初始化BSTIterator
类的一个对象。BST 的根节点root
会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。boolean hasNext()
如果向指针右侧遍历存在数字,则返回true
;否则返回false
。int next()
将指针向右移动,然后返回指针处的数字。注意,指针初始化为一个不存在于 BST 中的数字,所以对
next()
的首次调用将返回 BST 中的最小元素。你可以假设
next()
调用总是有效的,也就是说,当调用next()
时,BST 的中序遍历中至少存在一个下一个数字。
【输入样例】
["BSTIterator", "next", "next", "hasNext", "next", "hasNext", "next", "hasNext", "next", "hasNext"] [[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
【输出样例】
[null, 3, 7, true, 9, true, 15, true, 20, false]
解题思路:
对树进行中序遍历,存储节点信息在数组中,查询操作直接在数组中进行。
class BSTIterator{
private int idx;
private List arr;
public BSTIterator(TreeNode root){
idx = 0;
arr = new ArrayList();
inOrder(root,arr);
}
public int next(){
return arr.get(idx++);
}
public boolean hasNext(){
return idx < arr.size();
}
private void inOrder(TreeNode node, List arr){
if(node == null){
return;
}
inOrder(node.left,arr);
arr.add(node.val);
inOrder(node.right,arr);
}
}
/**
* 解法二,用栈,实时维护
class BSTIterator {
private TreeNode cur;
private Deque stack;
public BSTIterator(TreeNode root) {
cur = root;
stack = new LinkedList();
}
public int next() {
while(cur != null){
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
int ret = cur.val;
cur = cur.right;
return ret;
}
public boolean hasNext() {
return cur != null || !stack.isEmpty();
}
}
*/
时间: 击败了43.62%
内存: 击败了83.64%
题意:
给你一棵 完全二叉树 的根节点
root
,求出该树的节点个数。完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第
h
层,则该层包含1~ 2h
个节点。进阶:遍历树来统计节点是一种时间复杂度为
O(n)
的简单解决方案。你可以设计一个更快的算法吗
【输入样例】root=[1,2,3,4,5,6]
【输出样例】6
解题思路:
根据二叉树的特点,我们可以先判断,从根节点出发,左子树最左分支遍历的深度是否等于右子树最右分支遍历的深度,如果相等,是一颗满二叉树,很好计算;
如果不等,意味着这不是满二叉树,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照满二叉树情况来计算。
class Solution {
public int countNodes(TreeNode root) {
//满二叉树 2^高度 -1.(根节点的高度为0)
if(root == null) return 0;
TreeNode left = root.left;
TreeNode right = root.right;
int leftDepth =0,rightDepth = 0;
while(left != null){
left = left.left;
++leftDepth;
}
while(right != null){
right = right.right;
++rightDepth;
}
if(rightDepth == leftDepth){
return (2 << leftDepth) - 1;
}
//根节点记得要加上
return countNodes(root.left) + countNodes(root.right) + 1;
}
}
时间: 击败了100.00%
内存: 击败了13.81%
题意:
给定一个二叉树的 根节点
root
,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
【输入样例】[1,2,3,null,5,null,4]
【输出样例】[1,3,4]
解题思路:
层次遍历,并且记录每一层的深度是多少,利用map存储第depth层的节点值,因为是从左到右进行层次遍历,所以map中key=depth时的value一定是这一层的最右节点。
class Solution {
public List rightSideView(TreeNode root) {
Map map = new HashMap();
int max_depth = -1;
Queue nodeQueue = new LinkedList();
Queue depthQueue = new LinkedList();
nodeQueue.add(root);
depthQueue.add(0);//一个存节点信息,一个第几个节点
while(!nodeQueue.isEmpty()){
TreeNode node = nodeQueue.remove();
int depth = depthQueue.remove();
if(node != null){
max_depth = Math.max(max_depth,depth);
map.put(depth,node.val);//第depth层的最右侧节点
nodeQueue.add(node.left);
nodeQueue.add(node.right);
depthQueue.add(depth+1);
depthQueue.add(depth+1);
}
}
List right = new ArrayList();
for(int depth = 0; depth <= max_depth; ++depth){
right.add(map.get(depth));
}
return right;
}
}
时间: 击败了81.37%
内存: 击败了5.58%
题意:
给定一个非空二叉树的根节点
root
, 以数组的形式返回每一层节点的平均值。与实际答案相差10-5
以内的答案可以被接受。
【输入样例】root = [3,9,20,null,null,15,7]
【输出样例】[3.00000,14.50000,11.00000]
解题思路:深度优先搜索,借助两个列表,统计每一层的节点数和节点值和。
class Solution {
public List averageOfLevels(TreeNode root) {
List nums = new ArrayList();
List sums = new ArrayList();
List avgs = new ArrayList();
dfs(root,0,nums,sums);
int size = nums.size();
for(int i=0;i nums,List sums){
if(root == null){
return;
}
if(level < sums.size()){
sums.set(level,sums.get(level) + root.val);
nums.set(level,nums.get(level)+1);
}else{
sums.add(1.0 * root.val);
nums.add(1);
}
dfs(root.left,level+1,nums,sums);
dfs(root.right,level+1,nums,sums);
}
}
时间: 击败了100.00%
内存: 击败了82.36%
题意:
给你二叉树的根节点
root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
【输入样例】root = [3,9,20,null,null,15,7]
【输出样例】[[3],[9,20],[15,7]]
class Solution {
public List> levelOrder(TreeNode root) {
List> res = new ArrayList>();
if(root == null) return res;
Queue que = new LinkedList();//存储节点
que.add(root);
while(!que.isEmpty()){
List temp = new ArrayList();//存储每一层的节点
int depthSize = que.size();//当前层有多少个节点
for(int i=1;i<=depthSize;++i){
TreeNode node = que.poll();
temp.add(node.val);
if(node.left!=null){
que.add(node.left);
}
if(node.right != null){
que.add(node.right);
}
}
res.add(temp);
}
return res;
}
}
时间: 击败了91.04%
内存: 击败了27.87%
题意:
给你二叉树的根节点
root
,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
【输入样例】root = [3,9,20,null,null,15,7]
【输出样例】[[3],[20,9],[15,7]]
解题思路:在102题的基础上,添加一个变量,判断是从左到右还是从右到左,利用queue存在的addLast和addFirst实现不同情况下元素的添加顺序。
class Solution {
public List> zigzagLevelOrder(TreeNode root) {
List> res = new ArrayList>();
if(root == null) return res;
Queue que = new LinkedList();//存储节点
que.add(root);
boolean leftToRight = true;
while(!que.isEmpty()){
Deque temp = new LinkedList();//存储每一层的节点
int depthSize = que.size();//当前层有多少个节点
for(int i=1;i<=depthSize;++i){
TreeNode node = que.poll();
if(leftToRight){
temp.addLast(node.val);
}else{
temp.addFirst(node.val);
}
if(node.left!=null){
que.add(node.left);
}
if(node.right != null){
que.add(node.right);
}
}
res.add(new LinkedList(temp));
leftToRight = !leftToRight;
}
return res;
}
}
时间: 击败了72.75%
内存: 击败了26.27%