464. 我能赢吗【中等题】【每日一题】
思路:【博弈论DP】【三叶题解注释】
用一个二进制数
state
来表示[1,n]
范围内被选择的数的情况,二进制表示中从左到右,第i
(i
从0
开始)位为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();
*/