2465. 不同的平均值数目
给你一个下标从 0 开始长度为 偶数 的整数数组 nums
。
只要 nums
不是 空数组,你就重复执行以下步骤:
- 找到
nums
中的最小值,并删除它。 - 找到
nums
中的最大值,并删除它。 - 计算删除两数的平均值。
两数 a
和 b
的 平均值 为 (a + b) / 2
。
- 比方说,
2
和 3
的平均值是 (2 + 3) / 2 = 2.5
。
返回上述过程能得到的 不同 平均值的数目。
注意 ,如果最小值或者最大值有重复元素,可以删除任意一个。
提示
-
2 <= nums.length <= 100
-
nums.length
是偶数。 -
0 <= nums[i] <= 100
示例
思路
简单模拟
先排序,然后用双指针进行模拟,并用set
去重。
2466. 统计构造好字符串的方案数
给你整数 zero
,one
,low
和 high
,我们从空字符串开始构造一个字符串,每一步执行下面操作中的一种:
- 将
'0'
在字符串末尾添加 zero
次。 - 将
'1'
在字符串末尾添加 one
次。
以上操作可以执行任意次。
如果通过以上过程得到一个 长度 在 low
和 high
之间(包含上下边界)的字符串,那么这个字符串我们称为 好 字符串。
请你返回满足以上要求的 不同 好字符串数目。由于答案可能很大,请将结果对 10^9 + 7
取余 后返回。
提示:
-
1 <= low <= high <= 10^5
-
1 <= zero, one <= low
示例
思路
本质是个组合问题,可以将问题抽象成这样:x
初始为0,每次操作可以选择加上zero
或者one
,问经过若干次操作后,能使得x
位于[low, high]
区间内,总的操作方案数。
周赛当晚,最直观的想法当然就是暴力枚举了。然而由于最大的数据是low = 1
,high = 10^5
,zero = one = 1
,每次有2个选择,而一共可以做10^5
次选择,那么总的时间复杂度就能达到 ,这超时都超到太阳系外边去了。肯定是不行的。
看着这种每次加上一个数,有点动态规划那意思。于是就往动态规划上面想。
状态 f[i]
表示,构造出的字符串长度为i
时的总方案数。
接下来看状态转移,因为状态转移肯定跟某一次我们的选择有关系,而我们每次有2种选择。所以我们将状态数组开成二维,用f[i][0]
表示,最后一次选择的是zero
,且构造出的字符串长度为i
时的方案数;f[i][1]
表示,最后一次选择是one
。
对于f[i][0]
,由于最后一次选择的是zero
,则我们最后一次选择之前,得到的字符串长度是i - zero
,所以f[i][0] = f[i - zero][0] + f[i - zero][1]
同理,有f[i][1] = f[i - one][0] + f[i - one][1]
上面的代码还能优化,这里就不再赘述。
其实这道题就是爬楼梯。😓
2467. 树上最大得分和路径
一个 n
个节点的无向树,节点编号为 0
到 n - 1
,树的根结点是 0
号节点。给你一个长度为 n - 1
的二维整数数组 edges
,其中 edges[i] = [ai, bi]
,表示节点 ai
和 bi
在树中有一条边。
在每一个节点 i
处有一扇门。同时给你一个都是偶数的数组 amount
,其中 amount[i]
表示:
- 如果
amount[i]
的值是负数,那么它表示打开节点 i
处门扣除的分数。 - 如果
amount[i]
的值是正数,那么它表示打开节点 i
处门加上的分数。
游戏按照如下规则进行:
- 一开始,Alice 在节点
0
处,Bob 在节点 bob
处。 - 每一秒钟,Alice 和 Bob 分别 移动到相邻的节点。Alice 朝着某个 叶子结点 移动,Bob 朝着节点
0
移动。 - 对于他们之间路径上的
每一个
节点,Alice 和 Bob 要么打开门并扣分,要么打开门并加分。注意:
- 如果门 已经打开 (被另一个人打开),不会有额外加分也不会扣分。
- 如果 Alice 和 Bob 同时 到达一个节点,他们会共享这个节点的加分或者扣分。换言之,如果打开这扇门扣
c
分,那么 Alice 和 Bob 分别扣 c / 2
分。如果这扇门的加分为 c
,那么他们分别加 c / 2
分。
- 如果 Alice 到达了一个叶子结点,她会停止移动。类似的,如果 Bob 到达了节点
0
,他也会停止移动。注意这些事件互相 独立 ,不会影响另一方移动。
请你返回 Alice 朝最优叶子结点移动的 最大 净得分。
提示:
-
2 <= n <= 10^5
-
edges.length == n - 1
-
edges[i].length == 2
-
0 <= ai, bi < n
-
ai != bi
-
edges
表示一棵有效的树。 -
1 <= bob < n
-
amount.length == n
-
amount[i]
是范围 [-10^4, 10^4]
之间的一个 偶数 。
示例
思路
两次遍历
因为Alice
到达叶子节点有多种路径,但Bob
到达0
节点只有一种路径,当Alice
到达某个节点时,我们需要知道,在这一时刻,Bob
与这一节点的关系,无外乎下面三种
-
Bob
也恰好在这一时刻到达这一节点 -
Bob
在这一时刻之前已经到达过这一节点 -
Bob
还未到达过这一节点
所以,我们先通过一次遍历,找到Bob
的移动路径,并且对于这条路径上的每个节点,我们都能求出其与Bob
起始节点之间的距离(其实就代表了Bob
是在哪一个时刻到达该节点的)。随后,我们再进行一次遍历,让Alice
从0
号点出发,通过DFS遍历整个树,在经过每个节点时,我们容易得知当前节点与0
号节点之间的距离,故而能判断此时Bob
是否到达该节点,并能算出Alice
到达该节点的得分。遍历到叶子节点时,即找到一条可能的路径,用该路径的累加得分来更新答案即可。
2468. 根据限制分割消息
给你一个字符串 message
和一个正整数 limit
。
你需要根据 limit
将 message
分割 成一个或多个 部分 。每个部分的结尾都是 "<a/b>"
,其中 "b"
用分割出来的总数 替换, "a"
用当前部分所在的编号 替换 ,编号从 1
到 b
依次编号。除此以外,除了最后一部分长度 小于等于 limit
以外,其他每一部分(包括结尾部分)的长度都应该 等于 limit
。
你需要确保分割后的结果数组,删掉每部分的结尾并 按顺序 连起来后,能够得到 message
。同时,结果数组越短越好。
请你返回 message
分割后得到的结果数组。如果无法按要求分割 message
,返回一个空数组。
提示:
-
1 <= message.length <= 10^4
-
message
只包含小写英文字母和 ' '
。 -
1 <= limit <= 10^4
示例
思路
这是一道挺恶心的模拟题。周赛当天我读题读了半天愣是没读懂。
是这个意思,给一个字符串message
,尝试将其分为n
部分,第一部分的字符串,在后面加上<1/n>
,第二部分字符串在后面加上<2/n>
,…
使得加上这个<a/b>
后,每一部分字符串的长度都是limit
(最后一部分的长度可以小于limit
)。需要结果数组越短越好,就是n
越小越好。
首先,原字符串message
的长度是确定的,假设我们要分成n
部分,那么每一部分都会多出一个<a/b>
,总共n
部分(b = n
),多出的字符串长度总和是多少呢?容易发现,<a/b>
中,只有a
是变化的,其余部分都是固定的,除了a
,其余部分的长度是3
加上b
的位数(也就是n
的位数)。加上n
一共有k
位,那么这部分多出来的长度就是(3 + k) × n
。然后我们再来看a
,n
部分所有a
的长度之和,其实就是[1, n]
每个数字的位数之和。
假设n = 131
,则[1, 131]
中,
- 位数为1的数字为
1到9
,共9个数,长度之和为9; - 位数为2的数字为
10到99
,共90个数,长度之和为2 × 90 = 180 - 位数为3的数字为
100到131
,共32个数,长度之和为3 × 32 = 96
我们能很快计算出来所有数字的长度之和。
那么,当划分为n
部分时,我们就能算出总的字符串长度,此时再用总的字符串长度,除以limit
,看划分出来的是不是一共有n
个部分,若是,则说明满足条件。由于题目要求n
尽可能小,则我们从小开始枚举n
,找到第一个符合条件的n
即可。
总结
本场比赛只做出3题,T4读题花了太久时间。
T1是双指针简单模拟;T2是动态规划;T3是图的遍历;T4是模拟。