当前位置: 首页 > 知识库问答 >
问题:

找到许多方法来产生相等的总和?

司业
2023-03-14

所以,我试图解决这个问题:

你得到了数组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的所有数字的总和

共有3个答案

谯皓君
2023-03-14

正如您已经计算出的那样,首先找到整个数组的和。你没有提到负值的可能性。所以我假设它们是可能的。

接下来,找到包含第一个元素*的每个子阵列,其和正好等于总元素的三分之一。我们将这些称为左子阵列。这应该是O(n)。你需要记录所有这些结束的地方。

现在对包含最后一个元素*的每个子数组执行相同的操作,也就是O(n),还记录它们的开始位置(因为它们显然都在同一个位置结束)。我们称之为正确的子阵列

在不透露一切的情况下,现在找出非重叠*左子数组和右子数组的组合数。(因为很明显,它们之间的子数组也有所需的总和,即总数的1/3。如果你巧妙地完成这部分,它应该是O(左子数组的数量右子数组的数量),当然,这仍然是O(n)。

我在最后一段中遗漏了一个细节,是的,但我认为对于这些类型的挑战,很高兴给您留下一点挑战。整个过程应该在O(n)中是可能的

*我应该注意到,对于这个问题,基于空子数组的和是0还是未定义,在一些细节上存在一些差异。你也需要仔细考虑这一点。(根据这个例子,我想说空子数组的和是未定义的,这意味着非重叠也需要有非0长度的间隙)

乐正焕
2023-03-14

首先想到的是,您想找到两个拆分点,将数组绑定到恰好等于总和三分之一的子数组中:即从0到p1、p1到p2和p2到n-1。第二个是您想处理元素使您的总和超过目标值的情况。第三个是您想智能地处理数组中的零。

轩辕经赋
2023-03-14

正确的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