1145. Binary Tree Coloring Game [Medium]

https://leetcode.com/problems/binary-tree-coloring-game/

Two players play a turn based game on a binary tree.  We are given the root of this binary tree, and the number of nodes n in the tree.  n is odd, and each node has a distinct value from 1 to n.

Initially, the first player names a value x with 1 <= x <= n, and the second player names a value y with 1 <= y <= n and y != x.  The first player colors the node with value x red, and the second player colors the node with value y blue.

Then, the players take turns starting with the first player.  In each turn, that player chooses a node of their color (red if player 1, blue if player 2) and colors an uncolored neighbor of the chosen node (either the left child, right child, or parent of the chosen node.)

If (and only if) a player cannot choose such a node in this way, they must pass their turn.  If both players pass their turn, the game ends, and the winner is the player that colored more nodes.

You are the second player.  If it is possible to choose such a y to ensure you win the game, return true.  If it is not possible, return false.

Example 1:

Input: root = [1,2,3,4,5,6,7,8,9,10,11], n = 11, x = 3
Output: true
Explanation: The second player can choose the node with value 2.

Constraints:

  • root is the root of a binary tree with n nodes and distinct node values from 1 to n.
  • n is odd.
  • 1 <= x <= n <= 100
/**
 * 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) {}
 * };
 */

算法思路:

看看题目第一眼有点懵逼,example1给的解释实在是太烂了,直接误导人,什么玩意,在此翻译一下题目,顺便分析一下题意:

  • 有两个选手轮流玩一场游戏,其基于二叉树。给定一颗二叉树的根节点 root 和 节点总数 n,其中 n 是奇数,每个节点都是不同的值,范围是 1~n
  • 起初,第一个选手选定一个值 x1 <= x <= n,第二个选手选定一个值 y1 <= y <= n,且 y != x。第一个选手将 x 节点涂成红色,第二个选手将 y 节点涂成蓝色。
  • 然后,从第一个选手开始,两个选手轮流进行游戏。在每一轮中,选手可以选择一个与其同色(选手 1 为红色,选手 2 为蓝色)节点相邻且未涂色的节点,即该节点的左/右节点或者该节点的父节点均可。
  • 如果一个选手不能选到这样的节点,则轮到另一个选手。如果两个选手都不能,则游戏结束,节点涂色最多的一方获胜。

看了这么多,大致了解了,看起来挺复杂的,但注意三点:

  • 玩家1根据给定的x定位到初始红色节点位置;
  • 玩家2的蓝色节点在剩下的当中任意选择,但是要保证能color到最多的节点(以上两点确定初始位置);
  • 游戏开始的时候,都是基于已有的颜色节点向周边进行扩张的。

因此,我们没有必要实际的进行模拟一遍,我们知道红节点x是事先确定的,我们选择红节点的父亲节点、左子节点或者右子节点其中一个作为蓝色节点,如此就可以使得蓝色节点在初始就阻击红色节点的某一扩展方向,那么到底选择哪一个呢,那肯定选三个方向所含有的最多节点数的那一个,我们使用一个辅助函数,计算某一节点所对应子树的节点个数,一旦碰到node->val = x,那么我们就把xLeft,xRight记录下来并返回即可,很显然xParent = n - xLeft - xright - 1。那么最中只要知道其中一个值大于n / 2(n是奇数),就可以知道我们一定能赢,否则,我们一定会输。

基于此,example1中最贪心的选择 不是选择节点2,而是选择节点1,虽然结论是一致的。

class Solution {
public:
    bool btreeGameWinningMove(TreeNode* root, int n, int x) {
        int xLeft, xRight, xParent;
        countNode(root, x, xLeft, xRight);
        xParent = n - xLeft - xRight - 1;
        if (xLeft > n / 2 || xRight > n / 2 || xParent > n /2) return true;
        return false;
    } 
private:
    int countNode(TreeNode* node, const int& x, int& xLeft, int& xRight) {
        if (node == nullptr) return 0;
        int leftCount = countNode(node->left, x, xLeft, xRight);
        int rightCount = countNode(node->right, x, xLeft, xRight);
        if (node->val == x) {
            xLeft = leftCount;
            xRight = rightCount;
            return 0;
        }
        return 1 + leftCount + rightCount;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值