1. 找规律,数学归纳法证明
N | 说明 | 结果 |
---|---|---|
1 | Alice无法进行操作 | false |
2 | Alice选择1,bob无法进行操作 | ture |
3 | Alice选择1,bob选择1,Alice无法进行操作 | false |
4 | Alice选择1,剩余3,bob最终无法进行操作(alice选择2会导致false) | true |
规律:奇数false,偶数true
证明:
- N=1,N=2时满足结论
- 设2<N<=k时结论成立
- 当N=k+1,
1)k为偶数,k+1为奇数,奇数的因子为奇数,奇数减奇数为偶数,Alice选择 x x x, k + 1 − x < = k k+1-x <= k k+1−x<=k,bob开始选择,结论成立。
2)k为奇数,k+1为偶数,Alice选择1,bob从N=k开始必输,则Alice必胜。
class Solution {
public:
bool divisorGame(int N) {
return N%2 == 0;
}
};
时间复杂度:
O
(
1
)
O(1)
O(1);
空间复杂度:
O
(
1
)
O(1)
O(1)。
2. 动态规划
f [ i ] f[i] f[i]表示 N = i N=i N=i时的结果,显然, f [ 1 ] = f a l s e , f [ 2 ] = t r u e f[1] = false,f[2] = true f[1]=false,f[2]=true,遍历 i i i的因子 j j j,若存在 f [ i − j ] = f a l s e f[i-j]=false f[i−j]=false则说明此时Alice可以获胜,令 f [ i ] = t r u e f[i] = true f[i]=true。
class Solution {
public:
bool divisorGame(int N) {
vector<bool> f(N+1,false);
if(N<=1) return false;
f[1] = false;
f[2] = true;
for(int i=3; i<=N; ++i){
//遍历i的因子
for(int j=1; j<i; ++j){
if(!(i%j) && !f[i-j])//只要有一个因子可以令f[i-j]为false,说明Alice可以赢 !(i%j)括号
f[i] = true;
break;
}
}
return f[N];
}
};
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2);
空间复杂度:
O
(
n
)
O(n)
O(n)。