【Leetcode】第132场周赛

1025. 除数博弈

爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。

最初,黑板上有一个数字 N N N 。在每个玩家的回合,玩家需要执行以下操作:

选出任一 x x x,满足 0 &lt; x &lt; N 0 &lt; x &lt; N 0<x<N N N N % x = = 0 x == 0 x==0
N − x N - x Nx 替换黑板上的数字 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.valB.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. 树中的节点数在 25000 之间。
2. 每个节点的值介于 0100000 之间。

思路:类似于先序遍历的 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 maxnumminnum 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 &lt; = i 1 &lt; i 2 &lt; . . . &lt; i k &lt; = A . l e n g t h − 1 0 &lt;= i_1 &lt; i_2 &lt; ... &lt; i_k &lt;= A.length - 1 0<=i1<i2<...<ik<=A.length1。并且如果 B [ i + 1 ] − B [ i ] ( 0 &lt; = i &lt; B . l e n g t h − 1 ) B[i+1] - B[i]( 0 &lt;= i &lt; B.length - 1) B[i+1]B[i](0<=i<B.length1) 的值都相同,那么序列 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. 原始树中的节点数介于 11000 之间。
2. 每个节点的值介于 110 ^ 9 之间。

思路:用栈来存放节点。我们可以根据输入的串进行判断,首先记录 ′ − ′ &#x27;-&#x27; 出现的次数,即为该节点所在的深度 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();
    } 
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值