腾讯音乐TME 20220908笔试题解

T1

给定一个只包含小写字母字符串,每次可以选择两个相同的字符删除,并在字符串结尾新增任意一个小写字母。
请问最少多少次操作后,所有的字母都不相同?

字符串长度<1e3

input:
abab

output:
2

第一次把2个a变成f,第二次把2个b变成b。得到fb,每个字母都不相同,最少操作次数为2。

贪心就行了,每次把选2个字母变成当前出现次数最少的字母。因为字符串长度就1000,最多进行999次操作,每次操作遍历所有字母找出现次数最小的就可以。总体复杂度O(26n)

顺便做个follow-up,如果把字符串长度拉到1e5呢?其实可以以O(n)的解法来解。先考虑会消除多少次,对于某个字母出现m次,那么这个字母要操作m/2次使其变成0、1,同时产出m/2个字符,我们先把这产出的放到一边不考虑,先遍历所有字母,查看会产出多少字符。

得到产出字符数之后,可以遍历剩余的字母,根据上面所述,一个字母最终会剩下0/1,如果一个字母剩下0个,说明操作途中其他产出的字母就可以放到这个位置,不需要额外操作。否则产出的字符仍然需要额外操作。

考虑a~y每个字母都出现3次,z不出现。一共可以产出25个字母(a~y每个产出1个),同时a~y剩余1个,z剩余0个。那么因为有一个剩余0个的,前面在任意字母操作的时候,就可以直接往z这里放一个。这样还剩下24个产出,这产出的字母,每一个字母都需要额外操作一次,所以拢共需要操作24+25=49次。

class Solution:
    def minOperations(self, str: str) -> int:
        c = [0] * 26
        for i in str: c[ord(i) - ord('a')] += 1

        ans = 0
        more = 0
        for i in range(26):
            ans += c[i] // 2
            more += c[i] // 2
            c[i] %= 2
        for i in range(26):
            if c[i] == 0 and more:
                c[i] += 1
                more -= 1
        ans += more

        return ans

T2

题目描述
已知一个二叉树的先序遍历序列和中序遍历序列,但其中一些节点的值可能相同。
请你返回所有满足条件的二叉树。二叉树在数组中的顺序是任意的。

input: 
[1,1,2],[1,2,1]

output:
[{1,1,#,#,2},{1,#,1,2}]

case中会产出以下2个树:

图片说明

图片说明

经典递归。只需要枚举在中序遍历序列中每个可能成为下一个根节点的节点即可。因为是枚举的中序序列,那么假设某一个节点为根节点,这个节点左侧所有节点均为它的左子树,递归处理即可。

class Solution:
    def getBinaryTrees(self, preOrder: List[int], inOrder: List[int]) -> List[TreeNode]:
        if not preOrder: return [None]
        ans = []
        n = len(preOrder)

        for i in range(n):
            if inOrder[i] == preOrder[0]:
                for l in self.getBinaryTrees(preOrder[1:i + 1], inOrder[:i]):
                    for r in self.getBinaryTrees(preOrder[i + 1:], inOrder[i + 1:]):
                        node = TreeNode(preOrder[0])
                        node.left = l
                        node.right = r
                        ans.append(node)

        return ans

T3

给定一棵二叉树,二叉树的每个结点只有0或2个孩子。
你需要对每个结点赋值一个正整数,使得每个结点的左右子树权值和相等。
你需要返回所有结点的最小权值和对1e9+7取模的结果。
二叉树结点个数不超过1e5。

input:
{0,0,0}

output:
3

题目case如图:
图片说明

正常递归,因为两侧值相等,每次把左右子树小的值设置成大的值即可,然后本节点最小赋值为1。

不知道需不需要处理大数,反正Python不需要,其他语言可能需要注意一下long吧。

class Solution:
    def getTreeSum(self, tree: TreeNode) -> int:
        def f(node):
            return 0 if not node else max(f(node.left), f(node.right)) * 2 + 1

        return f(tree) % 1000000007
#腾讯音乐##笔试##题解##腾讯音乐2023秋招笔试心得体会#
全部评论
第一题思路能讲下吗
点赞 回复
分享
发布于 2022-09-08 21:04 湖北
第三题写的一样只过了55😅
4 回复
分享
发布于 2022-09-08 20:45 湖北
滴滴
校招火热招聘中
官网直投
跪了
1 回复
分享
发布于 2022-09-08 20:48 北京
感谢博主解答 另附上第一题后续为什么要直接加上more的原因: 如果此时more大于0,就代表26个slot每个slot都有一个字母 而more就是每次操作后多出来的字母 问题就转化为将more个字母全部消除的情况下,需要多少次 这里我们可以用具体的数字带入就好理解一点 比如说某个slot经过第一次消除后多出10个字母(注意此时原slot中必然还是有一个字母的) 那么这10个字母不断的对半消减,消减到最后为剩下1,所用次数是5+2+1+1,即9次 而此时最后原来还有一个字母,所以总共就是10次 数学归纳一下,就可以证明要把more个字母全部消除,需要more次合并
1 回复
分享
发布于 2022-09-09 11:53 广东
第一题贪心只过了60.。。
1 回复
分享
发布于 2022-09-09 11:55 北京
太牛了
点赞 回复
分享
发布于 2022-09-08 20:45 上海
太强了
点赞 回复
分享
发布于 2022-09-08 21:15 北京
点赞 回复
分享
发布于 2022-09-08 21:16 陕西
第二题真的太妙了,学习!
点赞 回复
分享
发布于 2022-09-08 21:35 上海
第二题的写法好清爽,
点赞 回复
分享
发布于 2022-09-09 09:32 上海
第三题不懂啥意思,按你的写法用例的根节点不应该是3吗?
点赞 回复
分享
发布于 2022-09-09 12:41 浙江
tql
点赞 回复
分享
发布于 2022-09-09 14:42 山东
第二题死活没想出来😭暴力拼接了
点赞 回复
分享
发布于 2022-09-09 17:22 广东
哎 其实题不算难 还是太菜了。。。
点赞 回复
分享
发布于 2022-09-10 16:32 北京
都用贪心了,第一题直接先统计有多少个字符没有出现过(如k),然后别2个2个减,尝试一次处理完一个字符的所有,或者k直接用完
点赞 回复
分享
发布于 2022-09-10 19:10 浙江

相关推荐

比亚迪深圳规划院 产品经理 0.9×1.36×12
点赞 评论 收藏
转发
38 128 评论
分享
牛客网
牛客企业服务