1145. 二叉树着色游戏
有两位极客玩家参与了一场「二叉树着色」的游戏。游戏中,给出二叉树的根节点 root,树上总共有 n 个节点,且 n 为奇数,其中每个节点上的值从 1 到 n 各不相同。
游戏从「一号」玩家开始(「一号」玩家为红色,「二号」玩家为蓝色),最开始时,
「一号」玩家从 [1, n] 中取一个值 x(1 <= x <= n);
「二号」玩家也从 [1, n] 中取一个值 y(1 <= y <= n)且 y != x。
「一号」玩家给值为 x 的节点染上红色,而「二号」玩家给值为 y 的节点染上蓝色。
之后两位玩家轮流进行操作,每一回合,玩家选择一个他之前涂好颜色的节点,将所选节点一个 未着色 的邻节点(即左右子节点、或父节点)进行染色。
如果当前玩家无法找到这样的节点来染色时,他的回合就会被跳过。
若两个玩家都没有可以染色的节点时,游戏结束。着色节点最多的那位玩家获得胜利 ✌️。
现在,假设你是「二号」玩家,根据所给出的输入,假如存在一个 y 值可以确保你赢得这场游戏,则返回 true;若无法获胜,就请返回 false。
示例:
输入:root = [1,2,3,4,5,6,7,8,9,10,11], n = 11, x = 3
输出:True
解释:第二个玩家可以选择值为 2 的节点。
提示:
二叉树的根节点为 root,树上由 n 个节点,节点上的值从 1 到 n 各不相同。
n 为奇数。
1 <= x <= n <= 100
解析过程:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/*
首先数字无序,不需要考虑数字顺序;其次,若能保证能够取得一半以上的节点数量,则可赢。因此,设置n个节点的一半为mid,用于后面判断。
若取父节点,则父节点以上的节点都属于同一个玩家;对于一个节点,若取其左(右)节点,则左(右)节点的所有节点都属于同一个玩家。
当一号玩家选取了x节点,先计算该节点的左右子树的节点数。可赢的条件为:
1. 如果left > mid 或者 right > mid, 则只要选取大于一半的那个节点,则必赢
2. 如果left + right < mid, 选取父节点,则总数超过一半,则必赢
会输的条件为:
1. left == mid 或者 right == mid, 无论选取哪个节点,其他另一边节点和父节点都是一号玩家的,一号玩家总数超过一半,都是必输
2. mid <= left + right < n, 无论选取哪个节点,其他另一边节点和父节点都是一号玩家的,一号玩家总数超过一半,都是必输
*/
int value;
int Left;
int Right;
public boolean btreeGameWinningMove(TreeNode root, int n, int x) {
value=x;
nums(root);
int mid=n/2;
if(Left>mid || Right>mid || (Left+Right)<mid){
return true;
}
return false;
}
//计算一号玩家选取x节点后,左右子树的节点数
public int nums(TreeNode node){
int Leftnumbers=0;
int Rightnumbers=0;
if(node.left!=null){
Leftnumbers= nums(node.left);
}
if(node.right!=null){
Rightnumbers= nums(node.right);
}
if(node.val==value){
Left=Leftnumbers;
Right=Rightnumbers;
}
return Leftnumbers+Rightnumbers+1;
}
}
结果:
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:36.2 MB, 在所有 Java 提交中击败了55.88%的用户
通过测试用例:65 / 65
971. 翻转二叉树以匹配先序遍历
给你一棵二叉树的根节点 root ,树中有 n 个节点,每个节点都有一个不同于其他节点且处于 1 到 n 之间的值。
另给你一个由 n 个值组成的行程序列 voyage ,表示 预期 的二叉树 先序遍历 结果。
通过交换节点的左右子树,可以 翻转 该二叉树中的任意节点。例,翻转节点 1 的效果如下:
请翻转 最少 的树中节点,使二叉树的 先序遍历 与预期的遍历行程 voyage 相匹配 。
如果可以,则返回 翻转的 所有节点的值的列表。你可以按任何顺序返回答案。如果不能,则返回列表 [-1]。
示例 1:
输入:root = [1,2], voyage = [2,1]
输出:[-1]
解释:翻转节点无法令先序遍历匹配预期行程。
示例 2:
输入:root = [1,2,3], voyage = [1,3,2]
输出:[1]
解释:交换节点 2 和 3 来翻转节点 1 ,先序遍历可以匹配预期行程。
示例 3:
输入:root = [1,2,3], voyage = [1,2,3]
输出:[]
解释:先序遍历已经匹配预期行程,所以不需要翻转节点。
解析过程:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/*
进行深度优先遍历。如果遍历到某一个节点的时候,节点值不能与行程序列匹配,那么答案为 [-1]。否则,当行程序列中的下一个期望数字 voyage[i] 与即将遍历的子节点的值不同的时候,需要翻转一下当前节点。
*/
List<Integer> list=new ArrayList<>();
int p;
int[] voyage;
public List<Integer> flipMatchVoyage(TreeNode root, int[] voyage) {
p=0;
this.voyage=voyage;
DFS(root);
if(!list.isEmpty() && list.get(0)==-1){
list.clear();
list.add(-1);
}
return list;
}
public void DFS(TreeNode node){
if(node!=null){
if(node.val!=voyage[p++]){
list.clear();
list.add(-1);
return;
}
if(node.left!=null && node.left.val!=voyage[p] && p<voyage.length){
list.add(node.val);
DFS(node.right);
DFS(node.left);
}else {
DFS(node.left);
DFS(node.right);
}
}
}
}
结果:
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.3 MB, 在所有 Java 提交中击败了79.04%的用户
通过测试用例:104 / 104
1161. 最大层内元素和
给你一个二叉树的根节点 root。设根节点位于二叉树的第 1 层,而根节点的子节点位于第 2 层,依此类推。
请你找出层内元素之和 最大 的那几层(可能只有一层)的层号,并返回其中 最小 的那个。
示例 1:
输入:root = [1,7,0,7,-8,null,null]
输出:2
解释:
第 1 层各元素之和为 1,
第 2 层各元素之和为 7 + 0 = 7,
第 3 层各元素之和为 7 + -8 = -1,
所以我们返回第 2 层的层号,它的层内元素之和最大。
示例 2:
输入:root = [989,null,10250,98693,-89388,null,null,null,-32127]
输出:2
解析过程:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int maxLevelSum(TreeNode root) {
if(root == null){
return 0;
}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
// 设置变量统计当前层数,最大值以及最终结果
int maxsum=Integer.MIN_VALUE;
int level=1,res=0;;
while(!queue.isEmpty()){
int size=queue.size();
// 在每一层维护一个计算每层元素之和的变量
int value=0;
for(int i=0;i<size;i++){
TreeNode cur=queue.poll();
value+=cur.val;
if(cur.left!=null){
queue.offer(cur.left);
}
if(cur.right!=null){
queue.offer(cur.right);
}
}
if(value>maxsum){
maxsum=value;
res=level;
}
level++;
}
return res;
}
}
结果:
执行用时:8 ms, 在所有 Java 提交中击败了83.10%的用户
内存消耗:41.5 MB, 在所有 Java 提交中击败了19.02%的用户
通过测试用例:40 / 40
965. 单值二叉树
如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。
只有给定的树是单值二叉树时,才返回 true;否则返回 false。
示例 1:
输入:[1,1,1,1,1,null,1]
输出:true
示例 2:
输入:[2,2,2,5,2]
输出:false
解析过程:
方法一:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//递归遍历每个节点,判断是否与根节点的值一样
boolean flag=true;
public boolean isUnivalTree(TreeNode root) {
int value=0;
if(root!=null){
value=root.val;
}
DFS(root,value);
return flag;
}
public void DFS(TreeNode node,int value){
if(node!=null){
if(node.val!=value){
flag=false;
return;
}
DFS(node.left,value);
DFS(node.right,value);
}
}
}
结果:
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:35.7 MB, 在所有 Java 提交中击败了92.04%的用户
通过测试用例:72 / 72
方法二:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//通过先序遍历将所有节点都加入list中,然后判断所有值是否相同
public boolean isUnivalTree(TreeNode root) {
List<Integer> list=new ArrayList<>();
Preorder(root,list);
/*int value=0;
if(root!=null){
value=root.val;
}
for(int i=0;i<list.size();){
if(list.get(i)==value){
i++;
}else{
return false;
}
}
*/
for(int value:list){
if(value!=list.get(0)){
return false;
}
}
return true;
}
public void Preorder(TreeNode node,List<Integer> list){
if(node==null){
return;
}
list.add(node.val)