所以,我试图解决这个问题:
你得到了数组a[1], a【2】, ..., a[n],由n个整数组成。计算将数组的所有元素拆分为三个连续部分的方法数,以便每个部分中的元素之和相同。
输入第一行包含整数n(1 ≤ n ≤ 5·10^5),显示数组中有多少个数字。第二行包含n个整数a[1],a[2]。。。,a【n】(| a【i】| ≤ 10^9)-数组a的元素。
输出打印一个整数-将数组拆分为具有相同总和的三部分的方法的数量。例如,
input
5
1 2 3 0 3
output
2
我的方法是:对所有输入的数字求和。找出它是否可以被3整除。如果不是,直接输出0,如果它可以被3整除,那么我们需要计算方法的数量。因此,我所做的是,
找到索引值(ind1,ind2,ind3),我可以找到满足给定条件的第一个子数组。也就是说,
int ind1=0,ind2=0,ind3=0;
while (ind1 < n)
{
p = p + arr[ind1];
if (p != val)
ind1++;
else if (p == val)
{
f1 = 1;
break;
}
}
ind2 = ind1;
ind2++;
p = 0;
while (ind2 < n)
{
p = p + arr[ind2];
if (p != val)
ind2++;
else if (p == val)
{
f2 = 1;
break;
}
}
ind3 = ind2;
ind3++;
p = 0;
while (ind3 < n)
{
p = p + arr[ind3];
if (p != val)
ind3++;
else if ( p == val )
{
f3 = 1;
//ans++;
break;
}
}
在我有了ind1、ind2、ind3之后,我开始检查0的存在,因为只有由于它们,我们才有不止一种方法。然而,我似乎没有从中得到正确的答案,例如,
Input:
9
0 0 0 0 0 0 0 0 0
正确的O/P应该是28,但我的是7。我的逻辑错了吗?
编辑:如建议:val=sum/3;//这里sum是(i=n-1; i的所有数字的总和
正如您已经计算出的那样,首先找到整个数组的和。你没有提到负值的可能性。所以我假设它们是可能的。
接下来,找到包含第一个元素*的每个子阵列,其和正好等于总元素的三分之一。我们将这些称为左子阵列。这应该是O(n)。你需要记录所有这些结束的地方。
现在对包含最后一个元素*的每个子数组执行相同的操作,也就是O(n),还记录它们的开始位置(因为它们显然都在同一个位置结束)。我们称之为正确的子阵列
在不透露一切的情况下,现在找出非重叠*左子数组和右子数组的组合数。(因为很明显,它们之间的子数组也有所需的总和,即总数的1/3。如果你巧妙地完成这部分,它应该是O(左子数组的数量右子数组的数量),当然,这仍然是O(n)。
我在最后一段中遗漏了一个细节,是的,但我认为对于这些类型的挑战,很高兴给您留下一点挑战。整个过程应该在O(n)中是可能的
*我应该注意到,对于这个问题,基于空子数组的和是0还是未定义,在一些细节上存在一些差异。你也需要仔细考虑这一点。(根据这个例子,我想说空子数组的和是未定义的,这意味着非重叠也需要有非0长度的间隙)
首先想到的是,您想找到两个拆分点,将数组绑定到恰好等于总和三分之一的子数组中:即从0到p1、p1到p2和p2到n-1。第二个是您想处理元素使您的总和超过目标值的情况。第三个是您想智能地处理数组中的零。
正确的O/P应该是28,但我的是7。我的逻辑错了吗?
对运行代码后,您将获得以下内容:
ind1 ind2 ind3
| | |
0 0 0 0 0 0 0 0 0 (1)
开始搜索零后,您会发现以下配置
ind1 ind2 ind3
| | |
0 0 0 0 0 0 0 0 0 (2)
ind1 ind2 ind3
| | |
0 0 0 0 0 0 0 0 0 (3)
ind1 ind2 ind3
| | |
0 0 0 0 0 0 0 0 0 (4)
ind1 ind2 ind3
| | |
0 0 0 0 0 0 0 0 0 (5)
ind1 ind2 ind3
| | |
0 0 0 0 0 0 0 0 0 (6)
ind1 ind2 ind3
| | |
0 0 0 0 0 0 0 0 0 (7)
这是您找到的7种配置。但这不是您想要的。首先,您只需要两个索引,而不是3,您的ind3应该始终指向最后一个元素。您需要计算3个和——从到0到ind1-1,从到ind1到ind2,从到ind2 1到n-1。所以你需要有那个ind1
ind1
|
ind2
|
0 0 0 0 0 0 0 0 0 (1)
ind1 ind2
| |
0 0 0 0 0 0 0 0 0 (2)
ind1 ind2
| |
0 0 0 0 0 0 0 0 0 (3)
...
ind1 ind2
| |
0 0 0 0 0 0 0 0 0 (7)
然后你也应该开始移动ind1
ind1
|
ind2
|
0 0 0 0 0 0 0 0 0 (8)
...
所以你得到的配置数量是:7 6 5 ... 1= 28
还要注意,这个算法是O(n^2),由于n最多可以达到10^5,这很可能会超时。因此,为了通过所有测试,您应该使用不同的方法。您可以做的是以下事情。首先计算数组索引集A={i|a[0]a[1]... a[i-1]=sum/3}和B={i|a[i 1]a[i 2]... a[n-1]=sum/3}。您可以将A和B存储在将被排序的数组中。现在,你要找的是对的数量(i,j),使得i来自A,j来自B,使得i
9
0 0 0 0 0 0 0 0 0
A={1,2,3,4,5,6,7}和B={1,2,3,4,5,6,7}(数组从0到8)。对于A中的索引1,你有满足问题的索引{1,2,3,4,5,6,7},对于A中的2,你有{2,3,4,5,6,7},等等。同样,你有7 6 5 4。。。1但不是列出所有可能的索引,而是使用二进制搜索在O(log n)时间内找到它们的计数。所以总的来说,你的算法是O(n log n)。
这是moreON思想的一个实现,它进一步扩展了二进制搜索的思想。不是每次迭代都重新开始二进制搜索,而是开始搜索之前找到的索引,该索引总共产生O(n)个摊销时间
#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
using namespace std;
int n;
long long sum, k;
int a[500010];
void solve()
{
scanf("%d", &n);
for (int i = 0; i < n; ++i)
scanf("%d", a + i);
for (int i = 0; i < n; ++i)
sum += a[i];
if (sum % 3 != 0) {
cout << 0 << endl;
return;
}
k = sum / 3;
vector<int> forward, backward;
sum = 0;
for (int i = 0; i < n-2; ++i) {
sum += a[i];
if (sum == k) {
forward.push_back(i+1);
}
}
sum = 0;
for (int i = n - 1; i >= 2; i--) {
sum += a[i];
if (sum == k) {
backward.push_back(i-1);
}
}
reverse(backward.begin(), backward.end());
int j = 0;
int fn = forward.size();
int bn = backward.size();
long long ans = 0;
for (int i = 0; i < fn; ++i) {
while (j < bn && backward[j] < forward[i])
j++;
ans += bn-j;
}
cout << ans << endl;
}
int main()
{
solve();
return 0;
}
给定一个值N,如果我们想换N美分,并且我们有无限量的S={S1,S2,…,Sm}值的硬币,我们可以用多少种方式来换?硬币的顺序无关紧要。例如,对于N=4和S={1,2,3},有四种解决方案:{1,1,1},{1,1,2},{2,2},{1,3}。所以输出应该是4。对于N=10和S={2,5,3,6},有五个解:{2,2,2,2,2},{2,2,3,3},{2,2,6},{2,3,5}和{5,5}。
本文向大家介绍javascript产生随机数方法汇总,包括了javascript产生随机数方法汇总的使用技巧和注意事项,需要的朋友参考一下 1.Math.random(); 结果为0-1间的一个随机数(包括0,不包括1) 2.Math.floor(num); 参数num为一个数值,函数结果为num的整数部分。 3.Math.round(num); 参数num为一个数值,函数结果为num四舍五入后的
使用野蝇8.2.0。最后,我相信使用焊接2.2,我已经在Maven多模块项目中用2个简单的类重现了这个问题。一个产生一个,另一个产生一个注入点。Arquillian部署失败与:不满足的依赖关系。生产者位于包含在消费者的WEB-INF/lib中的库jar中。生产者在META-INF中有一个,其中,消费者在WEB-INF中有一个。 复制步骤:下载此项目并从根目录运行。 这是一个关键错误。还有一些关于W
问题内容: 我正在尝试为对象编写一个equals方法,以比较它们的字段 并在相等时返回true。 这可能是什么问题? 问题答案: 由于color 似乎是一个Color,所以是一个类,因此是一个引用类型,这意味着您需要使用它们equals()来比较颜色。 如注释中所述,==用于比较引用类型实际上是比较Java中的内存地址。仅true当它们都 引用内存中的同一对象时,它才会返回。 akf指出,您需要为
我正在尝试制作具有nfc功能的应用程序。问题是,当nfc标签被发现时,挂起的意图总是会产生一个已经存在的新活动。我用的是tab主机。如何在不进行新活动的情况下制作悬挂帐篷。谢谢。
问题内容: 我一直在尝试各种Java代码,试图提出一些将对包含引号,空格和“奇异” Unicode字符的字符串进行编码的东西,并产生与JavaScript的encodeURIComponent函数相同的输出。 我的酷刑测试字符串是: “ A” B±“ 如果我在Firebug中输入以下JavaScript语句: —然后我得到: 这是我的小测试Java程序: —该程序输出: 靠近,但没有雪茄!使用Ja