【问题标题】:Count Total Subarrays having NEGATIVE PRODUCT in O(n)计算 O(n) 中具有负积的子数组总数
【发布时间】:2020-02-09 14:20:22
【问题描述】:

在一个由整数(负数、正数和零)组成的数组中
任务是找到 Total Number of subarrays 其乘积为 Negative

如果我找到所有子数组然后检查负积,它将进入 O(n^2)

long long n,a[200001],i,neg[200001],j;
long long totalneg=0; //前缀数组存储负元素的数量
辛>>n;
a[0]=0,负[0]=0;

for(i=1;i>a[i];
  如果(a[i]

那么我怎样才能在 O(n) 时间内找到它。

【问题讨论】:

  • 请向我们展示您目前拥有的代码。
  • 我不知道在这种情况下你会有什么时间复杂度,但你可以:1)获取数组大小(比如说n); 2) 找出所有负值; 3)让我们进入算法......如果你有奇数个负值,那么你肯定有一个负积,这与正值的数量无关。因此,您必须使用所有正值的组合以及负数的所有可能奇数乘法的组合。
  • 恐怕 Stackoverflow 不是家庭作业写作服务。向我们展示你做了什么,解释什么是不工作的,我们也许可以解决它。如果有帮助,如果数组有奇数个负数,它就会有一个负积?
  • 两个观察结果:(1)您的天真解决方案是 O(n^3),而不是 O(n^2) [您忘记了计算产品的成本]; (2) 思考动态规划。
  • 此外,如果你能写出时间复杂度为 O(n^2) 的解决方案,那就太好了。

标签: c++ math sub-array


【解决方案1】:

从第一个值开始:如果它是负数,你找到了其中一个子数组,如果它是正数,你找到了一个总和为正的子数组(稍后变为零)。

然后让我们考虑下一个值:如果是负数/正数,你找到了另一个这样的子数组。但是,您可以将它们与迄今为止找到的所有子数组结合起来!

如果你找到了np个正子数组,你会得到另一个np个正子数组,如果当前值为正数,或者另一个np个负数数组,如果当前值为负数,则类似地为负数nn 数组,只是你得到的新数组具有负积为正值,新数组具有正积为负值。

零的特殊值:包含在任何子数组中的这个值将产生零作为乘积,其他因素是什么已经无关紧要了。所以你可以在这一点停下来,将 nn 添加到某个总计数中,然后从 np 重新开始nn 为零。

考虑了数组中的所有数字后,不要忘记将最近计算的 nn 添加到总和中。

现在剩下的就是将该算法锻造成代码,这留给您...如果您在执行此操作时遇到问题,请随时提出一个新问题,提供您目前编写的代码。

【讨论】:

    【解决方案2】:

    我解决这个问题的方法如下:

    我们只关心数字的符号,因为我们不需要计算乘法的实际结果,我们可以轻松将输入转换为 1 和 -1,其中每个都代表一个正数如果给定数组是 {1,-2,3} 现在是 {1,-1,1},则分别是负整数。

    现在解决这个问题的关键是使用前缀乘法数组来跟踪答案,因为来自 [ i , j ] 的子数组当且仅当 prefix[ i ] * prefix[ j ] 因此:

    answer = #negative_numbers_prefix * #positive_numbers_prefix

    C++ 算法看起来像这样:

    int main() {
    int n,value;
    cin>>n;
    int positive=1,negative=0,prefix[n]; 
    for (int i=0;i<n;i++){
        cin>>value; 
        if (value>0){
            prefix[i]=1; 
        }else{
            prefix[i]=-1; 
        }
    
        if (i>0){
            prefix[i]*=prefix[i-1]; 
        }
    
        if (prefix[i]==1){ 
            positive++; 
        }else{
            negative++; 
        }
    } 
    int answer=negative*positive;
    cout<<answer<<endl;
    

    }

    注意:这个问题可能有一些变体,例如计算正子数组乘法而不是负数,在这种情况下,有一个非常方便的公式可以计算所有可能的子数组,即 ( N * ( N + 1 )) / 2 ) 所以如果你想计算正数,你只需要从总数中减去负数:( N * ( N + 1 ) ) / 2 - answer .

    【讨论】:

      【解决方案3】:

      "如果数组中包含整数 {-1 , 2, -3},则输出 4。但如果数组中包含整数 {-1, 2, -3, 0},则输出6 按照上面的解决方法。 我已经通过限制条件删除了这个bug,我的代码是"

      import java.io.*;
      public class Main1
      {
          public static void main(String[] args)throws IOException {
              BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
              int t = Integer.parseInt(br.readLine());
              while(t-->0){
                  int n = Integer.parseInt(br.readLine());
                  float a[] = new float[n];
                  long arr[] = new long[n];
                  long pos = 1,neg = 0;
                  String str[] = br.readLine().trim().split("\\s+");
                  for(int i=0;i<n;i++){
                      a[i] = Float.parseFloat(str[i]);
                  }
                  for(int i=0;i<n;i++) {
                      if(a[i]==0) {
                          break;
                      }
                      if(a[i]>0){
                          arr[i] = 1;
                      }else{
                          arr[i] = -1;
                      }
                      if(i>0){
                          arr[i] = arr[i]*arr[i-1];
                      }
                      if (arr[i]==1){ 
                          pos++; 
                      }else{
                          neg++; 
                      }
                  }
                  long ans = (pos*neg)%1000000007;
                  System.out.println(ans);
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-12
        • 1970-01-01
        • 2019-04-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多