当前位置:网站首页>【面试高频题】难度 3/5,可直接构造的序列 DP 题
【面试高频题】难度 3/5,可直接构造的序列 DP 题
2022-06-24 15:34:00 【宫水三叶的刷题日记】
题目描述
这是 LeetCode 上的 「1537. 最大得分」 ,难度为 「困难」。
Tag : 「前缀和」、「构造」、「双指针」、「序列 DP」、「动态规划」
你有两个 有序 且数组内元素互不相同的数组 nums1 和 nums2 。
一条 合法路径 定义如下:
选择数组 nums1或者nums2开始遍历(从下标 处开始)。从左到右遍历当前数组。 如果你遇到了 nums1和nums2中都存在的值,那么你可以切换路径到另一个数组对应数字处继续遍历(但在合法路径中重复数字只会被统计一次)。
得分定义为合法路径中不同数字的和。
请你返回所有可能合法路径中的最大得分。
由于答案可能很大,请你将它对 取余后返回。
示例 1: 
输入:nums1 = [2,4,5,8,10], nums2 = [4,6,8,9]
输出:30
解释:合法路径包括:
[2,4,5,8,10], [2,4,5,8,9], [2,4,6,8,9], [2,4,6,8,10],(从 nums1 开始遍历)
[4,6,8,9], [4,5,8,10], [4,5,8,9], [4,6,8,10] (从 nums2 开始遍历)
最大得分为上图中的绿色路径 [2,4,6,8,10] 。
示例 2:
输入:nums1 = [1,3,5,7,9], nums2 = [3,5,100]
输出:109
解释:最大得分由路径 [1,3,5,100] 得到。
示例 3:
输入:nums1 = [1,2,3,4,5], nums2 = [6,7,8,9,10]
输出:40
解释:nums1 和 nums2 之间无相同数字。
最大得分由路径 [6,7,8,9,10] 得到。
示例 4:
输入:nums1 = [1,4,5,8,9,11,19], nums2 = [2,3,4,11,12]
输出:61
提示:
nums1和nums2都是严格递增的数组。
前缀和 + 构造(分段计算)
一个简单且正确的做法,是我们构造一种决策方案,使得能够直接计算出最大得分。
首先,在最佳路径中所有的公共点都必然会经过,因此我们可以将值相等的点进行合并,即看作同一个点。
利用两个数组均满足「单调递增」,我们可以通过 的复杂度统计出那些公共点,以二元组 的形式存储到 list 数组(二元组含义为 )。
对于 list 中的每对相邻元素(相邻公共点),假设为 和 ,我们可以通过「前缀和」计算出 以及 的和,从而决策出在 (或者说是 ,这两个是同一个点)时,我们应当走哪一段。
当计算完所有公共点之间的得分后,对于最佳路线的首位两端,也是结合「前缀和」做同样的逻辑处理即可。
代码:
class Solution {
int MOD = (int)1e9 + 7;
public int maxSum(int[] nums1, int[] nums2) {
int n = nums1.length, m = nums2.length;
long[] s1 = new long[n + 10], s2 = new long[m + 10];
for (int i = 1; i <= n; i++) s1[i] = s1[i - 1] + nums1[i - 1];
for (int i = 1; i <= m; i++) s2[i] = s2[i - 1] + nums2[i - 1];
List<int[]> list = new ArrayList<>();
for (int i = 0, j = 0; i < n && j < m; ) {
if (nums1[i] == nums2[j]) list.add(new int[]{i, j});
if (nums1[i] < nums2[j]) i++;
else j++;
}
long ans = 0;
for (int i = 0, p1 = -1, p2 = -1; i <= list.size(); i++) {
int idx1 = 0, idx2 = 0;
if (i < list.size()) {
int[] info = list.get(i);
idx1 = info[0]; idx2 = info[1];
} else {
idx1 = n - 1; idx2 = m - 1;
}
long t1 = s1[idx1 + 1] - s1[p1 + 1], t2 = s2[idx2 + 1] - s2[p2 + 1];
ans += Math.max(t1, t2);
p1 = idx1; p2 = idx2;
}
return (int)(ans % MOD);
}
}
时间复杂度: 空间复杂度:
序列 DP
另外一个较为常见的做法是「序列 DP」做法。
定义 代表在 nums1 上进行移动,到达 的最大得分;定义 代表在 nums2 上进行移动,到达 的最大得分。
由于两者的分析是类似的,我们以 为例进行分析即可。
不失一般性考虑 如何转移,假设当前处理到的是 ,根据 是否为公共点,进行分情况讨论:
不为公共点,此时只能由 转移而来,即有 ; 为公共点(假设与 公共),此时能够从 或 转移而来,我们需要取 和 的最大值,即有 。
更重要的是,我们需要确保计算 时, 已被计算完成。
由于最佳路线必然满足「单调递增」,因此我们可以使用「双指针」来对 和 同时进行转移,每次取值小的进行更新,从而确保更新过程也是单调的,即当需要计算 时,比 小的 和 均被转移完成。
代码:
class Solution {
int MOD = (int)1e9 + 7;
public int maxSum(int[] nums1, int[] nums2) {
int n = nums1.length, m = nums2.length;
long[] f = new long[n + 1], g = new long[m + 1];
int i = 1, j = 1;
while (i <= n || j <= m) {
if (i <= n && j <= m) {
if (nums1[i - 1] < nums2[j - 1]) {
f[i] = f[i - 1] + nums1[i - 1];
i++;
} else if (nums2[j - 1] < nums1[i - 1]) {
g[j] = g[j - 1] + nums2[j - 1];
j++;
} else {
f[i] = g[j] = Math.max(f[i - 1], g[j - 1]) + nums1[i - 1];
i++; j++;
}
} else if (i <= n) {
f[i] = f[i - 1] + nums1[i - 1];
i++;
} else {
g[j] = g[j - 1] + nums2[j - 1];
j++;
}
}
return (int) (Math.max(f[n], g[m]) % MOD);
}
}
时间复杂度: 空间复杂度:
最后
这是我们「刷穿 LeetCode」系列文章的第 No.1537 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
更多更全更热门的「笔试/面试」相关的资料可访问排版精明的 合集新基地
边栏推荐
- Install the imagemagick7.1 library and the imageick extension for PHP
- Cloud + community [play with Tencent cloud] essay solicitation activity winners announced
- Convert text to hexadecimal, and reverse
- Teach you how to view version information with mongodb
- 手机同花顺股票开户安全吗!
- QoS Technology in network
- 运营商5G用户渗透远远比4G慢,5G的普及还得看中国广电
- Linux record -4.22 MySQL 5.37 installation (supplementary)
- Arrays API
- Improving the classification of motor imagery by combining EEG and MEG signals in BCI
猜你喜欢

我与“Apifox”的网络情缘

Wi-Fi 7 来啦,它到底有多强?

Vim编辑器的最常用的用法

MongoDB入门实战教程:学习总结目录

Solution to the problem that FreeRTOS does not execute new tasks

Solution of intelligent all in one machine in expressway service area

推荐几款超级实用的数据分析利器

FreeRTOS新建任务不执行问题解决办法

Logging is not as simple as you think

Most common usage of vim editor
随机推荐
Parameterized tests guide in junit5
[parameter configuration tutorial] how should the parameters in the RTMP streaming camera be configured?
Ascinema with asciicast2gif for efficient command line terminal recording
Detailed explanation of estab of Stata regression table output
A full set of tutorials for interviewers from Android manufacturers teach you: prepare for the interview and get the offer smoothly!
The first in China! Tencent cloud key management system passes password application verification test
Use dictionary
PHP application container deployment practice
Bosun query
【C语言刷题——Leetcode12道题】带你起飞,飞进垃圾堆
VNC Viewer方式的远程连接树莓派
国产芯片的赶超,让美国手机芯片龙头高通害怕了,出招应对竞争
中国产品经理的没落:从怀恋乔布斯开始谈起
Data stack technology sharing: how to use data stack for data collection?
Decomposition of Uber dependency injection into dig source code analysis
设备通过国标GB28181接入EasyCVR平台,出现断流情况该如何解决?
PHP export data as excel table
个人常用的高效工具
Poor remote code execution in Alien Swarm
How to efficiently transfer enterprise business data?