1025. 除数博弈
爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。
最初,黑板上有一个数字 N N N 。在每个玩家的回合,玩家需要执行以下操作:
选出任一
x
x
x,满足
0
<
x
<
N
0 < x < N
0<x<N 且
N
N
N %
x
=
=
0
x == 0
x==0 。
用
N
−
x
N - x
N−x 替换黑板上的数字
N
N
N 。
如果玩家无法执行这些操作,就会输掉游戏。
只有在爱丽丝在游戏中取得胜利时才返回 T r u e True True,否则返回 f a l s e false false。假设两个玩家都以最佳状态参与游戏。
示例 1:
输入:2
输出:true
解释:爱丽丝选择 1,鲍勃无法进行操作。
示例 2:
输入:3
输出:false
解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。
思路:根据题意,很容易得出规律,当 N N N为奇数时鲍勃获胜,当 N N N为偶数时爱丽丝获胜。
class Solution {
public:
bool divisorGame(int N) {
if (N % 2 == 0)
return true;
return false;
}
};
1026. 节点与其祖先之间的最大差值
给定二叉树的根节点 r o o t root root,找出存在于不同节点 A A A 和 B B B 之间的最大值 V V V,其中 V = ∣ A . v a l − B . v a l ∣ V = |A.val - B.val| V=∣A.val−B.val∣,且 A A A 是 B B B 的祖先。
(如果 A A A 的任何子节点之一为 B B B,或者 A A A 的任何子节点是 B B B 的祖先,那么我们认为 A A A 是 B B 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 得出。
提示:
1. 树中的节点数在 2 到 5000 之间。
2. 每个节点的值介于 0 到 100000 之间。
思路:类似于先序遍历的 d f s dfs dfs搜索。每搜一个节点,判断其值与 m a x n u m maxnum maxnum与 m i n n u m minnum minnum的大小并更新两者的大小;然后遍历左子树、右子树,当遍历到某个节点其左子树与右子树都为空时更新 m a x a n s maxans maxans的值,为 m a x n u m − m i n n u m maxnum-minnum maxnum−minnum与 m a x a n s maxans maxans的较大值
/**
* 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 maxans = 0;
int maxAncestorDiff(TreeNode* root) {
dfs(root, 100000, 0);
return maxans;
}
void dfs(TreeNode* root, int minnum, int maxnum) {
if (root->left == nullptr && root->right == nullptr) {
minnum = min(minnum, root->val);
maxnum = max(maxnum, root->val);
//更新maxans的值
maxans = max(maxans, maxnum - minnum);
return;
}
//更新maxnum与minnum的值
minnum = min(minnum, root->val);
maxnum = max(maxnum, root->val);
if (root->left)
dfs(root->left, minnum, maxnum);
if (root->right)
dfs(root->right, minnum, maxnum);
}
};
1027. 最长等差数列
给定一个整数数组 A A A,返回 A A A 中最长等差子序列的长度。
回想一下, A A A 的子序列是列表 A [ i 1 ] , A [ i 2 ] , . . . , A [ i k ] A[i_1], A[i_2], ..., A[i_k] A[i1],A[i2],...,A[ik] 其中 0 < = i 1 < i 2 < . . . < i k < = A . l e n g t h − 1 0 <= i_1 < i_2 < ... < i_k <= A.length - 1 0<=i1<i2<...<ik<=A.length−1。并且如果 B [ i + 1 ] − B [ i ] ( 0 < = i < B . l e n g t h − 1 ) B[i+1] - B[i]( 0 <= i < B.length - 1) B[i+1]−B[i](0<=i<B.length−1) 的值都相同,那么序列 B B B 是等差的。
示例 1:
输入:[3,6,9,12]
输出:4
解释:
整个数组是公差为 3 的等差数列。
示例 2:
输入:[9,4,7,2,10]
输出:3
解释:
最长的等差子序列是 [4,7,10]。
示例 3:
输入:[20,1,15,3,10,5,8]
输出:4
解释:
最长的等差子序列是 [20,15,10,5]。
思路:没有什么特别好的思路,唯有暴力破万法。查找时记录公差 A [ j ] − A [ i ] A[j] - A[i] A[j]−A[i],记录上一个公差序列数 n e x t = A [ j ] next=A[j] next=A[j],再来一层循环遍历查找公差为 A [ j ] − A [ i ] A[j]-A[i] A[j]−A[i]的序列,若找到 A [ k ] − n e x t = A [ j ] − A [ i ] A[k]-next=A[j]-A[i] A[k]−next=A[j]−A[i],则更新 n e x t = A [ k ] next=A[k] next=A[k],继续查找;每一趟查找之后更新等差序列长度
class Solution {
public:
int maxlen;
int longestArithSeqLength(vector<int>& A) {
if (A.size() <= 2)
return A.size();
for (int i = 0; i < A.size(); ++i) {
for (int j = i + 1; j < A.size(); ++j) {
int ans = A[j] - A[i]; //记录当前公差
int next = A[j]; //记录上一个等差序列值
int count = 2;
for (int k = j + 1; k < A.size(); ++k) {
if (A[k] - next == ans) {
count++;
next = A[k];
}
}
if (count > maxlen)
maxlen = count;
}
}
return maxlen;
}
};
1028. 从先序遍历还原二叉树
我们从二叉树的根节点 r o o t root root 开始进行深度优先搜索。
在遍历中的每个节点处,我们输出 D D D 条短划线(其中 D D D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D D D,则其直接子节点的深度为 D + 1 D + 1 D+1。根节点的深度为 0 0 0)。
如果节点只有一个子节点,那么保证该子节点为左子节点。
给出遍历输出 S S S,还原树并返回其根节点 r o o t root 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. 原始树中的节点数介于 1 和 1000 之间。
2. 每个节点的值介于 1 和 10 ^ 9 之间。
思路:用栈来存放节点。我们可以根据输入的串进行判断,首先记录 ′ − ′ '-' ′−′出现的次数,即为该节点所在的深度 d e p t h depth depth,然后将该节点的值计算出来为 a n s ans ans,并以 a n s ans ans构造一个新的节点;如果当前栈中节点数量大于该节点深度,则将栈首出栈,说明该节点不是栈首的子节点,然后再判断栈首的左子节点是否为空,如果为空则将新构造的节点作为栈首的左子节点,否则作为栈首的右子节点,将新构造的节点入栈;最后将栈中多余的节点出栈,只剩下一个节点即根节点,返回该节点
/**
* 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:
TreeNode* recoverFromPreorder(string S) {
stack<TreeNode*> st;
int i = 0;
int n = S.size();
while (i < n) {
int depth = 0, ans = 0;
//计算当前节点深度
while (i < n && S[i] == '-') {
depth++;
i++;
}
//计算节点值
while (i < n && S[i] != '-') {
ans = ans * 10 + S[i] - '0';
i++;
}
//判断是否为栈首子节点
while (st.size() > depth)
st.pop();
//以ans构造新节点
TreeNode* pNode = new TreeNode(ans);
//如果栈首左节点或右节点为空,则将新构造的节点作为栈首子节点
if (!st.empty() && st.top()->left == nullptr)
st.top()->left = pNode;
else if(!st.empty())
st.top()->right = pNode;
//将新构造的节点入栈
st.push(pNode);
}
//得到根节点
while (st.size() > 1)
st.pop();
return st.top();
}
};