我想找到将数组划分为3个连续部分的方法的数量,使得这三个部分的总和相等
-10^9 <= A[i] <= 10^9
我的方法: 输入和检查基础案例:
for(int i=0;i<n;i++){
a[i]= in.nextLong();
sum+=a[i];
}
if(sum%3!=0)System.out.println("0");
如果答案不在上面那么形成前缀和后缀总和。
for(int i=1;i<=n-2;i++){
xx+=a[i-1];
if(xx==sum/3){
dp[i]=1;
}
}
后缀求和更新二进制索引树
for(int i=n ;i>=3;i--){
xx+=a[i-1];
if(xx==sum/3){
update(i, 1, suffix);
}
}
现在简单地循环数组以找到Total Ways: int ans = 0;
for(int i=1;i<=n-2;i++){
if(dp[i]==1)
{
ans+= (query(n, suffix) - query(i+1, suffix));
// Checking For the Sum/3 in array where index>i+1
}
}
我对上述方法的答案错误
我不知道我在哪里犯了错误请帮助纠正我的错误。
更新和查询功能:
public static void update(int i , int value , int[] arr){
while(i<arr.length){
arr[i]+=value;
i+=i&-i;
}
}
public static int query(int i ,int[] arr){
int ans=0;
while(i>0){
ans+=arr[i];
i-=i&-i;
}
return ans;
}
答案 0 :(得分:3)
就你的方法而言,它是正确的。但是有一些观点因为它可能会给WA
说过在这里使用BIT树是一种矫枉过正,因为与 O(nlogn)解决方案相比,它可以在 O(n)中完成(但是如果你是在提交在线法官,那就无所谓了。
对于 O(n)方法,只需使用后缀[] 数组。并且如果已经标记后缀[i] = 1 从 i 到 n 是 sum / 3 ,向后遍历数组可以在 O(n)中完成。
然后再从后面再次遍历后缀[i] + =后缀[i-1] (除了基本情况i = n)。现在后缀[i] 存储索引数 i&lt; = j&lt; = n ,使得从索引 j 到 n 的总和为 sum / 3 ,这是你想用BIT实现的目标。
那么我建议你写一个暴力破解者或者这个简单的 O(n)并检查你的代码,
因为就你的方法而言,它是正确的,调试是不适合的
计算器。
答案 1 :(得分:1)
首先,我们计算一个数组dp
,其中dp [i] =从0到i的和,这可以在O(n)中完成
long[]dp = new long[n];
for(int i = 0; i < n; i++)
dp[i] = a[i];
if(i > 0)
dp[i] += dp[i - 1];
其次,假设数组的总和是x,所以我们需要找到哪个位置,我们有dp [i] == x / 3;
对于具有dp [i] == 2 * x / 3的每个i位置,我们需要添加到最终结果,索引j的数量&lt;我,dp[j] == x/3
。
int count = 0;
int result = 0;
for(int i = 0; i < n - 1; i++){
if(dp[i] == x/3)
count++;
else if(dp[i] == x*2/3)
result += count;
}
答案在result
。
您的方法有什么问题,
if(dp[i]==1)
{
ans+= (query(n, suffix) - query(i+1, suffix));
// Checking For the Sum/3 in array where index>i+1
}
这是错的,应该是
(query(n, suffix) - query(i, suffix));
因为,我们只需要删除1到i,而不是1到i + 1。
不仅如此,这一部分:
for(int i=1;i<=n-2;i++){
//....
}
应为i <= n - 1;
同样,此部分for(int i=n ;i>=3;i--)
应为i >= 1
第一部分:
for(int i=0;i<n;i++){
a[i]= in.nextLong();
sum+=a[i];
}
应该是
for(int i=1;i<=n;i++){
a[i]= in.nextLong();
sum+=a[i];
}
您的代码中存在许多小错误,您需要花费大量精力进行首先调试,跳到这里询问并不是一个好主意。
答案 2 :(得分:0)
在提出的问题中,我们需要在数组中找到三个连续的部分,它们的总和是相同的。 我将提及步骤以及将为您解决问题的代码片段。
我们正在做的事情是,从start开始遍历数组,直到len(array)-3。在找到总和,sum / 3,比如说索引i,我们有上半部分。
现在,不关心下半部分并将解决方案变量(启动为零)添加到等于end [i + 2]的值。 end [i + 2]告诉我们从i + 2开始到结束的总方式,得到的数量等于第三部分的sum / 3.
在这里,我们所做的是处理第一和第三部分,我们也处理了第二部分,它将默认等于sum / 3。我们的解决方案变量将是问题的最终答案。
以下是代码片段,以便更好地理解上述算法:: -
在这里,我们正在进行向后扫描,以存储从每个索引的末尾获得sum / 3的方式的数量。
long long int *end = (long long int *)calloc(numbers, sizeof(long long int);
long long int temp = array[numbers-1];
if(temp==sum/3){
end[numbers-1] = 1;
}
for(i=numbers-2;i>=0;i--){
end[i] = end[i+1];
temp += array[i];
if(temp==sum/3){
end[i]++;
}
}
一旦我们有了结束数组,我们就会进行前向循环并得到我们的最终解决方案
long long int solution = 0;
temp = 0;
for(i=0;i<numbers-2;i++){
temp+= array[i];
if(temp==sum/3){
solution+=end[i+2];
}
}
solution 存储最终答案,即将数组拆分为具有相等和的三个连续部分的方式的数量。