给定一个整数数组和一个整数m,如何找到包含m个奇数整数的所有子数组?下面是一个完整的问题,如果我的不够长的描述。有没有比n^2更快的解决方案?我下面的解决方案似乎是n^2,我不确定如何进一步优化它。
https://github.com/cem3394/hr-haskell/blob/master/beautifulsubarrays.hs
static long beautifulSubarrays(int[] a, int m) {
int sum = 0;
for (int i = 0; i < a.length; i++){
for (int j = i, c =0; j < a.length; j++){
if (a[j] %2 !=0){
c++;
}
if ((c==m) && (z==j)){
over = true;
sum++;
break
}
boolean over = false;
if (over) break;
for (int z = i, c = 0; z <= j; z++){
if (a[z]%2 != 0){
c++;
}
if (c>m){
over = true;
break;
}
if ((c==m) && (z==j)){
over = true;
sum++;
break;
}
}
}
}
return sum;
}
3条答案
按热度按时间hgqdbh6s1#
这是双指针方法的任务。
制作两个索引-l和r。
将l设置为0,将r从0向右移动,计算od计数器中的奇数。当od变为m时,记住r位置为r0。进一步移动r,直到满足新的奇数。
记住l位置为l0,并递增l直到满足奇数(如果[l0]为奇数,则保持不变)。
现在所有子数组都从
L0..L
范围和结束于R0..R-1
范围,正好包含m个奇数。有Cnt = (L-L0+1) * (R-R0)
这样的子阵列:所有从0..1开始到4..7结束的子数组都包含3个奇数,这里有2个开始索引和4个结束索引,所以
Cnt = 8
增量l,再次记住r0,重复此过程直到数组结束,为结果中设置的每个范围添加cnt指针只遍历数组一次,复杂性是线性的。
disbfnqx2#
想到了一个算法,但还没有机会验证其复杂性(我认为应该是o(n))
找出所有“最小”子数组
目的是找出以奇数开头和结尾的所有子数组。
以o(n)方式实现的一种方法是:对数组进行一次遍历,并记录所有奇数索引:
e、 g.输入
[ 2,3,4,6,7,1,10 ]
,你应该可以[1,4,5]
(索引1、4、5为奇数)假设子数组中有两个奇数,则为
[1,4]
以及[4,5]
###找出每个子数组的展开形式基本思想是,对于每个最小子数组,可以包含前面的奇数和后面的奇数。
以数组[4..5]为例:
您可以选择在偶数之前包含0、1或2。同时,您可以选择包含0或1个后续偶数。
也就是说,对于这个特定的子数组,有2*3=6“展开形式”
快速找到前/后偶数个数的方法很简单,只需从
[1,4,5]
至[-1,1,4,5,7]
. 索引4之前偶数的前一个数是4-1,即3,索引5之后偶数的后一个数是7-5,即2。通过对每个最小子阵的展开形式数求和,可以得到所需的结果。
knpiaxh13#
我在任何地方都找不到足够的解释来解释这个问题,所以我尽了最大的努力一步一步地解释这个问题。
下面是这个问题的js版本,时间复杂度为o(n)。
输入:arr-要处理的数组,m-要显示的整数数
返回:奇数为m的唯一子数组的数目
解释我们在这里所做的是计算可以形成的子阵列的总数,直到我们达到m个奇数,并将其保存到名为save的数组中。我们只需将其添加到我们的答案中,就可以得到可以形成的子阵列的总数。我们这样做直到我们到达最后一个元素。
考虑以下输入
第一步:
第二步:
第三步:
第四步:
第五步:
第6步:
第7步:
因为没有更多的元素存在,没有更多的子数组可以满足这个条件,ans返回8。