Codeing Interview: 最大值减去最小值小于或者等于num的子数组数量

题目大意:

给定一个数组array和数值num,计算出数组中有多少子数组,其最大值减去最小值满足小于或者等于num。

例如: 给定数组(1,2,3,4,5,10)和 num=3 ,则其中(1,2)子数组的最大值减去最小值为1,则满足条件。

要求:

时间复杂度O(N)。

解题思路

1 当我们使用暴力方法的时候,我们可以以i 作为子数组的开头,然后看看有多少个满足情况的子数组。这样的做法时间复杂度为O(N2)。
那么我们如何优化呢?当Array(i,j) 满足条件的时候,任意子数组Array(l,k),只要l>=i,k<=j,其都满足条件。
所以我们可以得出:当Array(i,j-1) 满足条件,Array(i,j) 不满足条件的时候,以i为开头的子数组个数为j-i.
接下来我们使用两个队列,分别记录Array[i,j]的最大值和最小值,并有两个下标索引,分别表示以i为子数组的开头,并且能满足条件的最大索引j.

代码如下:

public int getNum(int[] array,int num) {
        int  i = 0, j = 0;
        LinkedList<Integer> minQueue = new LinkedList<Integer>();
        LinkedList<Integer> maxQueue = new LinkedList<Integer>();
        int len = array.length;
        int res = 0;
        while(i < len){

            while(j<len){
                putMaxQueue(maxQueue,array,j);
                putMiQueue(minQueue,array,j);
                if(array[maxQueue.getFirst()] - array[minQueue.getFirst()] > num) {
                    break;
                } else {
                    j++;
                }
            }

            res += j-i;
            if(maxQueue.getFirst()<=i) {
                maxQueue.removeFirst();
            }
            if(minQueue.getFirst()<=i) {
                minQueue.removeFirst();
            }
            i++;
        }
        return res;

    }

    private void putMaxQueue(LinkedList<Integer> queue,int[]array,int index) {
        int e = array[index];
        while(!queue.isEmpty() && array[queue.peekLast()] <= e){
            queue.pollLast();
        }
        queue.add(index);
    }

    private void putMiQueue(LinkedList<Integer> queue,int[]array,int index) {
        int e = array[index];
        while(!queue.isEmpty() && array[queue.peekLast()] >= e) {
            queue.pollLast();
        }
        queue.add(index);
    }

猜你喜欢

转载自blog.csdn.net/zhumingyuan111/article/details/79518111
今日推荐