132
1025. 除数博弈
爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。
最初,黑板上有一个数字 N
。在每个玩家的回合,玩家需要执行以下操作:
- 选出任一
x
,满足0 < x < N
且N % x == 0
。 - 用
N - x
替换黑板上的数字N
。
如果玩家无法执行这些操作,就会输掉游戏。
只有在爱丽丝在游戏中取得胜利时才返回 True
,否则返回 false
。假设两个玩家都以最佳状态参与游戏。
示例 1:
输入:2
输出:true
解释:爱丽丝选择 1,鲍勃无法进行操作。
示例 2:
输入:3
输出:false
解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作》。
思路:动态规划,
f[i]
表示当数字是 i 时爱丽丝是否可以赢得比赛,如果i-j
时对面赢不了比赛,f[i-j]
置为1,最后返回f[N]
即可
class Solution {
public:
bool divisorGame(int N) {
vector<int> f(N+1);
for(int i=1;i<N+1;i++)
{
f[i]=0;
for(int j=1;j<i;j++)
{
if(i%j==0)
{
if(!f[i-j]) //f[i-j]表示此时对面的状态
{
f[i] = 1;
break;
}
}
}
}
return f[N];
}
};
## 1026. 节点与其祖先之间的最大差值
给定二叉树的根节点 root
,找出存在于不同节点 A
和 B
之间的最大值 V
,其中 V = |A.val - B.val|
,且 A
是 B
的祖先。
(如果 A 的任何子节点之一为 B,或者 A 的任何子节点是 B 的祖先,那么我们认为 A 是 B 的祖先)
示例:
输入:[8,3,10,1,6,null,14,null,null,4,7,13]
输出:7
解释:
我们有大量的节点与其祖先的差值,其中一些如下:
|8 - 3| = 5
|3 - 7| = 4
|8 - 1| = 7
|10 - 13| = 3
在所有可能的差值中,最大值 7 由 |8 - 1| = 7 得出。
思路:
思路: 深度优先遍历,对当前节点,分别计算当前节点值与目前最小与目前最大的差值,并记录每次遍历得到的最大差值,然后更新目前最小与目前最大。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int res;
int maxAncestorDiff(TreeNode* root) {
res = 0;
dfs(root,root->val,root->val);
return res;
}
void dfs(TreeNode* root,int l,int r)
{
if(root==NULL) return;
res = max(res,abs(root->val-l));
res = max(res,abs(root->val-r));
l = min(root->val,l);
r = max(root->val,r);
dfs(root->left,l,r);
dfs(root->right,l,r);
}
};
## 1027. 最长等差数列
给定一个整数数组 A
,返回 A
中最长等差子序列的长度。
回想一下,A
的子序列是列表 A[i_1], A[i_2], ..., A[i_k]
其中 0 <= i_1 < i_2 < ... < i_k <= A.length - 1
。并且如果 B[i+1] - B[i]
( 0 <= i < B.length - 1
) 的值都相同,那么序列 B
是等差的。
示例 1:
输入:[3,6,9,12]
输出:4
解释:
整个数组是公差为 3 的等差数列。
示例 2:
输入:[9,4,7,2,10]
输出:3
解释:
最长的等差子序列是 [4,7,10]。
思路:哈希表
对数组里每一个数字都开一个哈希表,记录此数字与其他数字差值为
t
的个数。
class Solution {
public:
int longestArithSeqLength(vector<int>& nums) {
int res = 0;
int n = nums.size();
vector<unordered_map<int,int>> hash(n);
for(int i=1;i<n;i++)
{
for(int j=0;j<i;j++)
{
int t = nums[i]-nums[j];
hash[i][t] = hash[j][t]+1; //hash[j][t]初始为0
res = max(res,hash[i][t]);
}
}
return res+1;
}
};
## 1028. 从先序遍历还原二叉树
我们从二叉树的根节点 root
开始进行深度优先搜索。
在遍历中的每个节点处,我们输出 D
条短划线(其中 D
是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。
如果节点只有一个子节点,那么保证该子节点为左子节点。
给出遍历输出 S
,还原树并返回其根节点 root
。
示例 1:
输入:"1-2--3--4-5--6--7"
输出:[1,2,5,3,4,6,7]
示例 2:
输入:"1-2--3---4-5--6---7"
输出:[1,2,5,3,null,6,null,4,null,7]
示例 3:
输入:"1-401--349---90--88"
输出:[1,401,null,349,88,90]
提示:
- 原始树中的节点数介于
1
和1000
之间。 - 每个节点的值介于
1
和10 ^ 9
之间。
思路:做了注释,代码思路很清晰,要注意的是字符串序列需要转化成数字形式。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int pos = 0; //记录当前遍历到的位置,总指针
string T;
inline int read_val(int p) {
int x = 0;
for (; p < T.length() && isdigit(T[p]); ++ p)
x = (x * 10) + (T[p] - '0');
return x;
}
TreeNode* Dfs(int dep) {
int cur = 0; //记录 '-' 的个数,表示下一个节点的深度
for (int j = pos; j < T.length() && T[j] == '-'; ++ j) ++ cur;
if (cur != dep) return NULL;
pos += cur;
TreeNode *u = new TreeNode(read_val(pos));
while (pos < T.length() - 1 && isdigit(T[pos])) ++ pos; //跳过第一个数字后面的数字,在函数里已经计算过了
u -> left = Dfs(dep + 1);
u -> right = Dfs(dep + 1);
return u;
}
TreeNode* recoverFromPreorder(string S) {
T = S; return Dfs(0);
}
};
这一题代码来自这位大神:zjp-shadow
这场周赛有两道深度优先遍历的题目,这个知识点还是非常重要的,以后也要多做点这方面的题目。