[每日一题2020.06.16] leetcode双周赛T3 5423 找两个和为目标值且不重叠的子数组 DP, 前缀和

题目链接

给你一个整数数组 arr 和一个整数值 target 。

请你在 arr 中找 两个互不重叠的子数组 且它们的和都等于 target 。可能会有多种方案,请你返回满足要求的两个子数组长度和的 最小值 。

请返回满足要求的最小长度和,如果无法找到这样的两个子数组,请返回 -1 。

一个map用来保存从0-index i 的前缀和以及索引 ------mp[前缀和] = 索引

一个dp用来保存不大于目前索引i的最小长度的子数组长度, 如果不存在, 则为maxn

用一个sum做累加, 同时对map进行更新

可知当mp中含有sum - target时可以找到一个子数组

设置cur = 找到的新子数组长度

bfindex = 此数组之前的(与之不重叠的) 序号

1592108705114

则可以由是否存在dp[bfindex]判断此前是否已经有符合条件的数组

如果有:

\[ans = min (ans, cur + dp[bfindex]) \]

不管有没有 :

\[dp[i] = min(dp[i-1], cur) \]

注意当i==0的特殊情况, 不然会造成数组访问越界, 这里我用了个if判断

ac代码 :

int minSumOfLengths(vector<int>& arr, int target) {
	const int maxn = 0x3f3f3f3f;
	int n = arr.size();
	int sum = 0;
	int ans = maxn;
	vector<int> dp(n, maxn);
	map<int, int> mp;
	mp[0] = -1;
	for (int i = 0; i < n; ++i)
	{
		sum += arr[i];
		
		if(i)
			dp[i] = dp[i - 1];
		if (mp.count(sum - target)) { 
			int cur = i - mp[sum - target];
			int bfindex = mp[sum - target];
			if (bfindex >= 0 && dp[bfindex] < maxn) {
				ans = min(ans, cur + dp[bfindex]);
			} 
			if(i)
				dp[i] = min(dp[i-1], cur);
			else
				dp[i] = min(cur, maxn);
		}
		mp[sum] = i;
	}
	return ans == maxn ? -1 : ans;
}
posted @ 2020-06-14 12:34  roccoshi  阅读(151)  评论(0编辑  收藏  举报