leetcode 第 404 场算法比赛

作者: | 更新日期:

DP题比较多。

本文首发于公众号:天空的代码世界,微信号:tiankonguse

零、背景

个人感觉题目不难,我卡了好一会,竟然排名 36。

A: 枚举。
B: 动态规划。
C: 动态规划。
D: 动态规划+贪心。

排名:36
代码地址: https://github.com/tiankonguse/leetcode-solutions/tree/master/contest/4/404

一、三角形的最大高度

题意:给两个颜色的球。
要求摆一个三角形,每一行球的颜色相同,比上一行多一个球,不同行的球的颜色要求不同。
问最多可以摆多少行。

思路:枚举计算

显然,隔一行球的颜色相同。
假设可以摆 n 行,则可以根据奇偶性计算出奇偶行分别累计需要多少个球。
从小到大枚举答案,判断两个颜色的球是否满足奇偶行累计的球即可。

二、找出有效子序列的最大长度 I

题意:给一个数组,求一个子序列,使得子序列所有相邻位置元素之和的奇偶性相同。
求最长的子序列。

思路:动态规划。

显然,答案分两种情况:

情况1:所有元素奇偶性相同。
情况2:隔一个元素,奇偶性相同。

对于情况1,统计奇偶性个数即可。
对于情况2,奇偶性是交叉出现的,需要动态规划来做。

状态:dp(n, flag) 前 n 个元素,子序列最后位置奇偶性为 flag 的最长序列长度。
方程:

dp(n, flag) = dp(n-1, 1-flag) + 1;
dp(n, 1-flag) = dp(n-1, 1-flag);

优化:观察方程,可以发现当前状态只依赖上个状态,所以可以使用滚动数组。

方程:

dp(flag) = dp(1-flag) + 1;

三、找出有效子序列的最大长度 II

题意:给一个数组,求一个子序列,要求相邻子序列之和与 K 取模后都相等,求最长子序列。

思路:动态规划,与第二题相似,不优化即可。

显然,答案分两种情况:

情况1:所有元素取模后都相同。
情况2:隔一个元素,取模后值相同。

状态:dp(n, a, b) 前 n 个元素,子序列为 a,b交叉出现,最后位置取为 b 的最长序列长度。
方程:

dp(n, i, v) = dp(n-1, v, i) + 1;

优化:观察方程,可以发现当前状态只依赖上个状态,所以可以使用滚动数组。

方程:

dp(i, v) = dp(v, i) + 1;

同时可以发现,当 i 等于 v 时,就是第一种情况。
所以情况2的答案是覆盖情况1的,这里就不需要单独统计每个元素出现的次数了。

四、合并两棵树后的最小直径

题意:给两个树,问怎么使用一条边把两个树连起来,使得树的直径最小。

思路:动态规划+贪心。

树的直径定义为树中任意两个节点之间的最长路径长度。

根据这个定义,可以推导出一个几个推论。

推论1:假设非直径上的点 C 与直径 [A,B]的交点是为 D,则 CD 不大于 ADBD

推论2:这道题两个树连接点必然在直径上。

假设不在直径上,不妨假设在 (D,C] 线段上,即为点 E。

另外假设 AD >= DB,根据推论1,可以推导出 AD>DB>=CD>=ED

如果新形成的树的直径经过两个树,则直径在这个树的线段必然为 AD+ED

可以证明,E 点越接近 D 点,这个树上的直径线段会越小。
即交点在直径上 D 上时,会比不在直径上更优。

推论3:连接在直径的中间最优。

推论2已经证明了两个树合并后的直径线段为 AD
那显然 AD 越短越好。
由于 AD >= DB, 故故D 在直径的中间是最优的。

有了上面的推论,这道题得到这道题的算法。

1、求出两棵树的直径
2、合并后,树的直径可能不变,也可能变大。
变大时,直径由连接线和两个树的半径组成。

那如何求一棵树的直径呢?

思路1:贪心两边 dfs。
可以证明:任意选择一个点当做子树,深度最长路径的叶子节点肯定是直径的一个端点。
证明:见上面的推论1。
所以找到一个直径端点后,再dfs一边,就可以找到另外一个端点了。

思路2:树形DP。
递归求出每个子树经过子树根的最长路径。
经过根的最长路径:找到经过根的最长两条边,求和即可。

具体实现的时候,有很多优化,具体可以参考模版:

https://github.com/tiankonguse/leetcode-solutions/tree/master/doc/graph/tree

五、最后

这次比赛第一题其实也可以使用动态规划,这样的话四道题就都是动态规划了。

《完》

-EOF-

本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号ID:tiankonguse-code

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越