我需要澄清这个问题的答案,但我不能评论(没有足够的代表),所以我问一个新的问题。希望没问题。
问题是这样的:
给定一个数组,你必须找到最大可能的两个相等的总和,你可以排除元素。
即1,2,3,4,6是给定的数组,我们可以得到最大两个相等的和,如6 2 = 4 3 1
即4,10,18,22,我们可以得到两个相等的和,因为18 4=22
除了蛮力寻找所有计算并检查两个可能的相等和之外,你解决这个问题的方法是什么?
编辑1:数组元素的最大数量为N
编辑 2:元素总和不能大于 1000。
被认可的回答说:
我建议使用DP来解决这个问题,这里不跟踪A,B(两个集合的大小),而是跟踪A,B,A-B(两组的和和和和差)。
然后对于数组中的每个元素,尝试将其添加到A或B,或两者都不添加。
跟踪和/差的好处是,你只需要跟踪每个差的单个值,即你看到的这个差的和的最大值。
我不明白的是:
如果这是一个子集和问题,我可以用DP来解决它,有一个记忆矩阵(N x P),其中N是集合的大小,P是目标和。。。
但是我无法弄清楚我应该如何跟踪A B,A-B(正如批准答案的作者所说)。哪些应该是记忆矩阵的维度?以及这如何帮助解决问题?
答案的作者非常友好地提供了一个代码示例,但我很难理解,因为我不懂python(我懂java)。
#include <bits/stdc++.h>
using namespace std;
/*
Brute force recursive solve.
*/
void solve(vector<int>&arr, int &ans, int p1, int p2, int idx, int mx_p){
// if p1 == p2, we have a potential answer
if(p1 == p2){
ans = max(ans, p1);
}
//base case 1:
if((p1>mx_p) || (p2>mx_p) || (idx >= arr.size())){
return;
}
// leave the current element
solve(arr, ans, p1, p2, idx+1, mx_p);
// add the current element to p1
solve(arr, ans, p1+arr[idx], p2, idx+1, mx_p);
// add the current element to p2
solve(arr, ans, p1, p2+arr[idx], idx+1, mx_p);
}
/*
Recursive solve with memoization.
*/
int solve(vector<vector<vector<int>>>&memo, vector<int>&arr,
int p1, int p2, int idx, int mx_p){
//base case 1:
if((p1>mx_p) || (p2>mx_p) || (idx>arr.size())){
return -1;
}
// memo'ed answer
if(memo[p1][p2][idx]>-1){
return memo[p1][p2][idx];
}
// if p1 == p2, we have a potential answer
if(p1 == p2){
memo[p1][p2][idx] = max(memo[p1][p2][idx], p1);
}
// leave the current element
memo[p1][p2][idx] = max(memo[p1][p2][idx], solve(memo, arr, p1, p2,
idx+1, mx_p));
// add the current element to p1
memo[p1][p2][idx] = max(memo[p1][p2][idx],
solve(memo, arr, p1+arr[idx], p2, idx+1, mx_p));
// add the current element to p2
memo[p1][p2][idx] = max(memo[p1][p2][idx],
solve(memo, arr, p1, p2+arr[idx], idx+1, mx_p));
return memo[p1][p2][idx];
}
int main(){
vector<int>arr = {1, 2, 3, 4, 7};
int ans = 0;
int mx_p = 0;
for(auto i:arr){
mx_p += i;
}
mx_p /= 2;
vector<vector<vector<int>>>memo(mx_p+1, vector<vector<int>>(mx_p+1,
vector<int>(arr.size()+1,-1)));
ans = solve(memo, arr, 0, 0, 0, mx_p);
ans = (ans>=0)?ans:0;
// solve(arr, ans, 0, 0, 0, mx_p);
cout << ans << endl;
return 0;
}
试试这个dp方法:它工作正常。
/*
*
i/p ::
1
5
1 2 3 4 6
o/p : 8
1
4
4 10 18 22
o/p : 22
1
4
4 118 22 3
o/p : 0
*/
import java.util.Scanner;
public class TwoPipesOfMaxEqualLength {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t-- > 0) {
int n = sc.nextInt();
int[] arr = new int[n + 1];
for (int i = 1; i <= n; i++) {
arr[i] = sc.nextInt();
}
MaxLength(arr, n);
}
}
private static void MaxLength(int[] arr, int n) {
int dp[][] = new int[1005][1005];
int dp1[][] = new int[1005][1005];
// initialize dp with values as 0.
for (int i = 0; i <= 1000; i++) {
for (int j = 0; j <= 1000; j++)
dp[i][j] = 0;
}
// make (0,0) as 1.
dp[0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= 1000; j++) {
for (int k = 0; k <= 1000; k++) {
if (j >= arr[i]) {
if (dp[j - arr[i]][k] == 1) {
dp1[j][k] = 1;## Heading ##
}
}
if (k >= arr[i]) {
if (dp[j][k - arr[i]] == 1) {
dp1[j][k] = 1;
}
}
if (dp[j][k] == 1) {
dp1[j][k] = 1;
}
}
}
for (int j = 0; j <= 1000; j++) {
for (int k = 0; k <= 1000; k++) {
dp[j][k] = dp1[j][k];
dp1[j][k] = 0;
}
}
}
int ans = 0;
for (int i = 1; i <= 1000; i++) {
if (dp[i][i] == 1) {
ans = i;
}
}
System.out.println(ans);
}
}
我认为思考这个解决方案与单个子集问题的关系可能会误导你。这里我们关心的是一个最大可实现的和,而且,当我们遍历时,我们需要区分两组不相交的数。显然,跟踪特定的组合成本太高。
看看A组和B组的区别,我们可以说:
A - B = d
A = d + B
显然,当 d = 0
时,我们想要最高的总和。我们怎么知道这个总和?这是(A B)/ 2
!
对于动态程序中的转换,我们想知道将当前元素放在A、B还是两者都不放更好。这是这样实现的:
e <- current element
d <- difference between A and B
(1) add e to A -> d + e
why?
A = d + B
(A + e) = d + e + B
(2) add e to B -> d - e
why?
A = d + B
A = d - e + (B + e)
(3) don't use e -> that's simply
what we already have stored for d
让我们看看Peter de Rivas的过渡代码:
# update a copy of our map, so
# we can reference previous values,
# while assigning new values
D2=D.copy()
# d is A - B
# s is A + B
for d,s in D.items():
# a new sum that includes element a
# we haven't decided if a
# will be in A or B
s2 = s + a
# d2 will take on each value here
# in turn, once d - a (adding a to B),
# and once d + a (adding a to A)
for d2 in [d-a, d+a]:
# The main transition:
# the two new differences,
# (d-a) and (d+a) as keys in
# our map get the highest sum
# seen so far, either (1) the
# new sum, s2, or (2) what we
# already stored (meaning `a`
# will be excluded here)
# so all three possibilities
# are covered.
D2[abs(d2)] = max(D2[abs(d2)], s2)
最后,我们存储了在 d = 0 时看到的最高 A B,其中 A 和 B 中的元素形成不相交的集合。返回 (A B) / 2.
给定一个数组,你必须找到最大可能的两个相等的总和,你可以排除元素。 即给定数组,我们可以有最大两个相等的和,因为6 2=4 3 1 即 4,10,18, 22,我们可以得到两个相等的总和,因为 18 4 = 22 除了蛮力寻找所有计算并检查两个可能的相等和之外,你解决这个问题的方法是什么? 编辑1:数组元素的最大数目为N 编辑2:这是我的解决方案,https://ideone.com/cAbe4g
我正在用MapReduce框架用Java制作一个Hadoop应用程序。 对于输入和输出,我只使用文本键和值。在减少到最终输出之前,我使用一个合并器来做额外的计算。 但我有一个问题,钥匙不去同一个减速器。我在组合器中创建和添加了这样的键/值对: 基本上,我创建的工作如下: 减速机打印的标准输出如下: 这是没有意义的,因为键是相同的,因此它应该是2个还原器,其中3个值是相同的 希望你能帮我弄清这件事:
问题内容: 我想在哈希图中搜索键,然后找到与该键最接近的键! 因此,基本上我想搜索一个long,如果地图中不存在该long,则找到与该long值最接近的匹配项!我怎样才能做到这一点!? 提前感谢 问题答案: 如果不迭代其所有键,就无法做到这一点。我假设这不是您想要的,所以这是一种使用的方法:
问题内容: 如果我保存包含以下列表的对象 我例外 播放中的代码!控制器看起来像这样: 如果我在此块之前插入它会起作用,但是位置信息会丢失(这会导致其他错误)。 这是Hibernate错误还是我的代码有问题? 问题答案: 问题是,这Hibernate不支持的组合和。如果没有Hibernate,则使用联接表,一切都会按预期进行。
问题内容: 我有一套清单: 我要s1∩s2∩s3 … 我可以编写一个函数来执行一系列成对的操作,等等。 有没有推荐,更好或内置的方法? 问题答案: 从python版本2.6开始,您可以对使用多个参数,例如 如果这些集合在列表中,则表示为: 这里是列表扩展 请注意,是 不是 一个静态的方法,但这种使用功能符号应用第一套交叉口列表的其余部分。因此,如果参数列表为空,则将失败。
给定n个非负整数a1, a2,..., an,其中每个表示坐标(i, ai)处的点。绘制n条垂直线,使得线i的两个endpoint位于(i, ai)和(i,0)。找到两条线,它们与x轴一起构成一个容器,使得容器中包含最多的水。 注意:容器不能倾斜。 一种解决方案可能是我们取每一行并找到每一行的区域。这需要O(n^2)。没有时间效率。 另一种解决方案是使用DP找到每个索引的最大面积,然后在索引n处,