计算在 O(n) 中具有负积的子数组总数
Count Total Subarrays having NEGATIVE PRODUCT in O(n)
在由整数(负数,正数和零(
组成的数组中,任务是找到乘积为负数的子数组的总数。
如果我找到所有子数组,然后检查负积,它将进入O(n^2(。
long long n,a[200001],i,neg[200001],j; long long totalneg=0; //prefix array to store number of negative element cin>>n; a[0]=0,neg[0]=0; for(i=1;i<=n;i++) { cin>>a[i]; if(a[i]<0) neg[i]=neg[i-1]+1; else neg[i]=neg[i-1]; } for(i=1;i<=n;i++) { for(j=i;j<=n;j++) { if( (neg[j]-neg[i-1]) %2 !=0 ) totalneg++; } } cout<<totalneg;那么我如何在O(n(时间内找到它。
从第一个值开始:如果它是负数,则找到其中一个子数组,如果它是正数,则找到一个具有正和的子数组(稍后为零(。
然后让我们考虑下一个值:如果为负/为正,则您找到了另一个这样的子数组。但是,您可以将它们与到目前为止找到的所有子数组组合在一起!
如果您找到了 n p 个正子数组,如果当前值为正,则得到另一个 n p 个正子数组,或者如果当前值为负,则得到另一个 np个负数组,类似于负 nn 个数组的计数,只是你得到新数组的负积为正值和新数组的正积为负值。
特殊值为零:任何子数组中包含的此值都将产生零作为乘积,其他因素是什么已经无关紧要了。因此,您可以在此时停止,将 n n添加到某个总数中,然后重新开始,其中 np和 nn 为零。
考虑了数组中的所有数字后,不要忘记将最新计算的 nn 添加到总和中。
现在剩下的就是将这个算法锻造成代码,留给你......如果您遇到麻烦,请随时提出一个新问题,提供您到目前为止编写的代码。
我解决这个问题的方式如下:
我们只关心数字的符号,因为我们不被要求计算乘法的实际结果,我们可以轻松地将输入转换为 1 和 -1,其中每个分别表示一个正整数和一个负整数,如果给定数组是 {1,-2,3} 现在它是 {1,-1,1}。
现在解决这个问题的关键是使用前缀乘法数组来跟踪答案,因为来自 [ i , j ] 的子数组有一个否定的结果,当且仅当前缀 [i ] * 前缀 [ j ] <0 因此:
答案 = #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 - 答案。
"如果数组包含整数 {-1, 2, -3}。然后它将给出输出 4。但是如果数组包含整数 {-1, 2, -3, 0}。然后它将按照上述解决方案给出输出 6。 我已经通过限制条件删除了错误,我的代码是">
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);
}
}
}
- cpp二进制搜索问题,计算给定数组中输入元素的出现次数
- C++数据文件、数组和计算赋值
- 如何计算数组中元素的位数?(不是数组的长度),并计算其数字的总和
- 我的目标是编写一个程序来计算和存储字符串在字符数组中出现的位置
- 从另一个静态常量数组初始化静态常量数组(只需少量计算)
- 有效地计算多维数组的累积和?
- 通过指针算法计算数组长度
- 计算数组重复次数的组合的有效算法,加起来达到给定的总和
- 给定一个单词数组和一个字符串,如何计算给定字符串中的所有单词
- 使用结构数组计算文本文件中单词的出现次数C++
- 使用 2D 数组计算总计、最高价和最低价
- 二维数组:计算行的总和和列的乘积
- 从字符数组计算平均数
- 练习:使用数组计算方差
- 二维数组计算公式
- 从导入的二维数组计算平均值
- 从数组计算数据的c++问题
- 通过二维数组计算文件中的特定记录
- Python模拟显示慢性能,如何加快数组计算速度
- 通过数组计算文本文件数值数据