Java 查找具有指定数量的奇数整数的子阵列数
给定一个整数数组和一个整数m,如何找到包含m个奇数整数的所有子数组?下面是一个完整的问题,如果我的不够长的描述。有没有比n^2更快的解决方案?我下面的解决方案似乎是n^2,我不确定如何进一步优化它Java 查找具有指定数量的奇数整数的子阵列数,java,arrays,algorithm,Java,Arrays,Algorithm,给定一个整数数组和一个整数m,如何找到包含m个奇数整数的所有子数组?下面是一个完整的问题,如果我的不够长的描述。有没有比n^2更快的解决方案?我下面的解决方案似乎是n^2,我不确定如何进一步优化它 静态长数组(int[]a,int m){ 整数和=0; for(int i=0;i
静态长数组(int[]a,int m){
整数和=0;
for(int i=0;i
考虑了一个算法,但没有机会验证其复杂性(我认为应该是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]为例:
[ 2,3,4,6,7,1,10 ]
^ ^
您可以选择在偶数之前包含0、1或2。同时,您可以选择包含0或1个偶数
也就是说,对于这个特定的子数组,有2*3=6个“扩展形式”
通过将子数组索引从[1,4,5]
略微修改为[-1,1,4,5,7]
,快速找到前面/后面偶数的数量是很容易的。索引4之前偶数的前一个数是4-1,即3,索引5之后偶数的后一个数是7-5,即2
通过对每个最小子数组的展开形式数求和,可以得到所需的结果。这是双指针方法的任务 制作两个索引-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)
这样的子阵列:
m=3
L0 L R0 R
i 0 1 2 3 4 5 6 7 8
A[i] 4 1 3 2 5 6 2 2 3
所有从0..1开始到4..7结束的子数组都包含3个奇数,这里有2个索引用于开始,4个索引用于结束,因此Cnt=8
增量L,再次记住R0,重复此过程直到数组结束,为结果中设置的每个范围添加Cnt
指针只遍历数组一次,复杂性是线性的。我在任何地方都找不到足够的解释来解释这个问题,所以我已经尽了最大努力一步一步地解释这个问题 下面是这个问题的JS版本,时间复杂度为O(n) 输入:arr-要处理的数组,m-要存在的整数数 返回:正好有m个奇数的唯一子数组的数目
function beautifulArray(arr, m) {
var noOfOddNumbersSoFar = 0;
var ans = 0;
var save = []; // Save possible number of sub arrays till i with m odd numbers
for (var i = 0; i < arr.length; i++) {
if (save[noOfOddNumbersSoFar]) {
save[noOfOddNumbersSoFar]++;
} else {
save[noOfOddNumbersSoFar] = 1;
}
noOfOddNumbersSoFar += arr[i] % 2 == 0 ? 0 : 1;
if (noOfOddNumbersSoFar >= m) {
ans += save[noOfOddNumbersSoFar - m];
}
}
return ans;
}
步骤1:
noOfOddNumbersSoFar = 0
save[noOfOddNumbersSoFar] is set to 1. i.e, save = [1]
i = 0
arr[i] is 2 (even)
noOfOddNumbersSoFar remains 0
步骤2:
noOfOddNumbersSoFar = 0
save[noOfOddNumbersSoFar] is set to 2. i.e, save = [2]
i = 1
arr[i] is 2 (even)
noOfOddNumbersSoFar remains 0
步骤3:
noOfOddNumbersSoFar = 0
save[noOfOddNumbersSoFar] is set to 3. i.e, save = [3]
i = 2
arr[i] is 5 (odd)
noOfOddNumbersSoFar is set to 1
步骤4:
noOfOddNumbersSoFar = 1
save[noOfOddNumbersSoFar] is set to 1. i.e, save = [3, 1]
i = 3
arr[i] is 6 (even)
noOfOddNumbersSoFar remains 1
步骤5:
noOfOddNumbersSoFar = 1
save[noOfOddNumbersSoFar] is set to 2. i.e, save = [3, 2]
i = 4
arr[i] is 9 (odd)
noOfOddNumbersSoFar is set to 2
noOfOddNumbersSoFar is >= m(2)
noOfOddNumbersSoFar - m
So we take the number of possible subarrays from the saved variable save[0] and add it to ans. ans = 3
Here 3 denotes [2, 2, 5, 6, 9], [2, 5, 6, 9] and [5, 6, 9].
步骤6:
noOfOddNumbersSoFar = 2
save[noOfOddNumbersSoFar] is set to 1. i.e, save = [3, 2, 1]
i = 5
arr[i] is 2 (even)
noOfOddNumbersSoFar remains 2
noOfOddNumbersSoFar is >= m(2)
noOfOddNumbersSoFar - m is still 0
So we take the number of possible subarrays from the saved variable save[0] and add it to ans. ans = 3 + 3 = 6
We are adding 3 more to the ans. It denotes three more sub arrays which can meet the condition. They are [2, 2, 5, 6, 9, 2], [2, 5, 6, 9, 2] and [5, 6, 9, 2].
We have addressed [2, 2, 5, 6, 9], [2, 5, 6, 9], [5, 6, 9], [2, 2, 5, 6, 9, 2], [2, 5, 6, 9, 2] and [5, 6, 9, 2] so far. // ans = 6
步骤7:
noOfOddNumbersSoFar = 2
save[noOfOddNumbersSoFar] is set to 2. i.e, save = [3, 2, 2]
i = 6
arr[6] is 11 (odd)
noOfOddNumbersSoFar is set to 3
noOfOddNumbersSoFar is >= m(2)
noOfOddNumbersSoFar - m is still 1
So we take the number of possible subarrays from the saved variable save[1] and add it to ans. ans = 6 + 2 = 8
We are adding 2 more to the ans. It denotes two more sub arrays which can meet the condition. They are [6, 9, 2, 11] and [9, 2, 11].
We have addressed [2, 2, 5, 6, 9], [2, 5, 6, 9], [5, 6, 9], [2, 2, 5, 6, 9, 2], [2, 5, 6, 9, 2], [5, 6, 9, 2], [6, 9, 2, 11] and [9, 2, 11] so far. // ans = 8
由于没有更多的元素,因此没有其他子数组可以满足此条件,将ans返回为8。import java.util.HashSet;
import java.util.HashSet;
public class subarray {
public static void main(String[] args) {
// int numbers[] = {1, 2, 3, 4};
// int numbers[] = {6, 3, 5, 8};
// int kk = 1;
int numbers[] = {2, 1, 2, 1, 3};
int kk = 2;
HashSet<Integer> evenElements = new HashSet<>();
HashSet<Integer> oddElements = new HashSet<>();
int count = 0;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 == 0) {
evenElements.add(numbers[i]);
} else {
oddElements.add(numbers[i]);
}
}
for (int i = 0; i < numbers.length; i++) {
for (int j = i + 1; j < numbers.length; j++) {
int odd = 0;
for (int k = i; k <= j; k++) {
boolean flag = true;
for (int l = 0; l < i; l++) {
if (numbers[l] == numbers[i] && numbers[l + 1] == numbers[j]) {
flag = false;
}
}
if (flag) {
if (numbers[k] % 2 != 0) {
odd = odd + 1;
}
}
}
if (odd != 0 && odd <= kk) {
count = count + 1;
}
}
}
System.out.println(count + oddElements.size() + evenElements.size());
}
}
公共类子阵{
公共静态void main(字符串[]args){
//整数[]={1,2,3,4};
//整数[]={6,3,5,8};
//int kk=1;
整数[]={2,1,2,1,3};
int kk=2;
HashSet=newhashset();
HashSet oddElements=新HashSet();
整数计数=0;
for(int i=0;inoOfOddNumbersSoFar = 2
save[noOfOddNumbersSoFar] is set to 2. i.e, save = [3, 2, 2]
i = 6
arr[6] is 11 (odd)
noOfOddNumbersSoFar is set to 3
noOfOddNumbersSoFar is >= m(2)
noOfOddNumbersSoFar - m is still 1
So we take the number of possible subarrays from the saved variable save[1] and add it to ans. ans = 6 + 2 = 8
We are adding 2 more to the ans. It denotes two more sub arrays which can meet the condition. They are [6, 9, 2, 11] and [9, 2, 11].
We have addressed [2, 2, 5, 6, 9], [2, 5, 6, 9], [5, 6, 9], [2, 2, 5, 6, 9, 2], [2, 5, 6, 9, 2], [5, 6, 9, 2], [6, 9, 2, 11] and [9, 2, 11] so far. // ans = 8
import java.util.HashSet;
public class subarray {
public static void main(String[] args) {
// int numbers[] = {1, 2, 3, 4};
// int numbers[] = {6, 3, 5, 8};
// int kk = 1;
int numbers[] = {2, 1, 2, 1, 3};
int kk = 2;
HashSet<Integer> evenElements = new HashSet<>();
HashSet<Integer> oddElements = new HashSet<>();
int count = 0;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 == 0) {
evenElements.add(numbers[i]);
} else {
oddElements.add(numbers[i]);
}
}
for (int i = 0; i < numbers.length; i++) {
for (int j = i + 1; j < numbers.length; j++) {
int odd = 0;
for (int k = i; k <= j; k++) {
boolean flag = true;
for (int l = 0; l < i; l++) {
if (numbers[l] == numbers[i] && numbers[l + 1] == numbers[j]) {
flag = false;
}
}
if (flag) {
if (numbers[k] % 2 != 0) {
odd = odd + 1;
}
}
}
if (odd != 0 && odd <= kk) {
count = count + 1;
}
}
}
System.out.println(count + oddElements.size() + evenElements.size());
}
}