查找具有指定奇数整数的子数组的数量

时间:2017-09-05 02:30:23

标签: java arrays algorithm

给定一个整数数组和一个整数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;


    }

4 个答案:

答案 0 :(得分:7)

这是双指针方法的任务。

制作两个索引 - L和R.

将L设置为0并将R从0向右移动,计算Od计数器中的奇数。当Od变为m时,记住R位置为R0。进一步移动R直到满足新的奇数。

记住L位置为L0并增加L直到满足奇数(如果A [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

指针仅遍历数组一次,复杂性是线性的。

答案 1 :(得分:2)

想到一个算法,但没有机会验证复杂性(我相信应该是O(n))

找出所有“最小”子阵列

目的是找出所有以奇数开始和结束的子阵列。

以O(n)方式实现它的一种方法是:对数组进行一次单次传递,并记录所有奇数的索引:

e.g。输入[ 2,3,4,6,7,1,10 ],您应该能够获得[1,4,5](索引1,4,5是奇数)

假设你想在子阵列中有2个奇数,它是[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。

通过总结每个最小子阵列的扩展形式数量,您可以获得所需的结果。

答案 2 :(得分:1)

我无法在任何地方找到足够的解释来解释这个问题所以我已经尝试了我的水平,一步一步解释这个问题。

以下是此问题的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;
}

<强>解释 我们在这里做的是计算可以形成的子阵列的总数,直到达到m个奇数并将其保存到名为 save 的数组中。我们只是将其添加到我们的答案中,以获得可以形成的子阵列的总数。我们这样做直到我们到达最后一个元素。

考虑以下输入

arr = [2,2,5,6,9,2,11];
m = 2;

第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。

答案 3 :(得分:1)

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());
    }
}