464. 我能赢吗 / 剑指 Offer II 055. 二叉搜索树迭代器

464. 我能赢吗【中等题】【每日一题】

思路:【博弈论DP】【三叶题解注释】

用一个二进制数state来表示[1,n]范围内被选择的数的情况,二进制表示中从左到右,第i(i0开始)位为1表示数字i+1被选中,否则表示数字i+1没被选中。

代码:

class Solution {
    //定义全局变量 n 表示 可选择的数的范围 t 表示 当前的目标总和
    int n , t ;
    //用于记录状态变量,可选择的数最大有20种,因此 f 的长度为 1 << 20 位
    int[] f = new int[1<<20];

    public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
        //初始化将maxChoosableInteger赋值给 n desiredTotal 赋值给 t
        n = maxChoosableInteger;
        t = desiredTotal;
        //如果 t = 0 那么先手方肯定赢 直接返回true
        if (t == 0){
            return true;
        }
        //如果 将 [1,n]范围内所有的整数全部累加依然小于 t 那么先手方必然输掉,因为不管怎么选,都不能使累加整数和 >= 目标总和 ,此时按照规则判定先手方输掉,直接返回false
        if (n * (n + 1) / 2 < t){
            return false;
        }
        //调用dfs函数进行模拟游戏
        return dfs(0,0) == 1;
    }

    /**
     *  模拟游戏
     * @param state 起始状态
     * @param tot 当前累加总和
     * @return 返回当前累加和是否 >= t 是则返回 1 不是则返回 -1
     */
    public int dfs(int state,int tot){
        //如果当前状态值不为0 表示当前状态的数字已被选过,于是直接返回当前状态值
        if (f[state] != 0){
            return f[state];
        }
        //遍历[1,n]每一个可选数字,用二进制表示的话就是从右到左遍历每一个二进制位置
        for (int i = 0; i < n; i++) {
            //取出状态state二进制表示右移 i 位后 & 1 如果 结果为 1 说明 数字 1 << i 已被选中过,继续下一个数字的判断
            if (((state >> i) & 1) == 1){
                continue;
            }
            // 如果 当前累加总和 >= t 说明当前选中的这个数字 i+1 (i与实际数字差1,所以这里要+1) 满足题意
            if (tot + i + 1 >= t){
                //将当前状态标记为 1 并返回 1
                return f[state] = 1;
            }
            //如果 当前累加总和 < t 那么就从当前数字和当前累加总和开始,dfs搜索对手方是否能实现 >= t
            if (dfs(state | (1 << i),tot + i + 1) == -1){
                //dfs过后,如果得到的结果为 -1 说明对手方失败,那么也将当前状态标记为 1 并返回 1
                return f[state] = 1;
            }
        }
        //如果所有的可选数字都选了一遍,未能成功返回1,说明当前进行游戏的一方必然失败,返回-1
        return f[state] = -1;
    }
}

剑指 Offer II 055. 二叉搜索树迭代器【中等题】

思路:

使用迭代法将二叉搜索树按从小到大的顺序展开为一个只有右节点的二叉树。
具体解法参考剑指 Offer II 052. 展平二叉搜索树

在构造函数中求出展平后的二叉搜索树,并将树的根节点赋给全局变量 index,接下来就简单了,题目要求的指针的初始值是一个值小于BST最小值的任意数,右节点指向 展平后的根节点 index 。因此,函数next返回的就是当前节点index的值,调用后将index移动到下一个右节点位置。只要当前节点index不为null,那么函数hasNext返回的就是true

代码:

/**
 * 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 BSTIterator {
    TreeNode index;
    public BSTIterator(TreeNode root) {
        Deque<TreeNode> deque = new ArrayDeque<>();
        TreeNode node = root,head = null;
        while(node != null || !deque.isEmpty()){
            while(node != null){
                deque.addLast(node);
                node = node.right;
            }
            node = deque.removeLast();
            node.right = head;
            head = node;
            node = node.left;
            head.left = null;
        }
        this.index = head;
    }
    
    public int next() {
        int val = index.val;
        index = index.right;
        return val;
    }
    
    public boolean hasNext() {
        if(index == null){
            return false;
        }
        return true;
    }
}

/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator obj = new BSTIterator(root);
 * int param_1 = obj.next();
 * boolean param_2 = obj.hasNext();
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值