栈和队列----最大值减去最小值小于等于num的子数组的数量

最大值减去最小值小于等于num的子数组的数量

  

  给定数组arr和整数 num,共返回有多少个数组满足下列情况: max(arr[i..j])-min(arr[i..j])<=num。其中max(arr[i..j]) 表示子数组arr[i..j] 中的最大值,min(arr[i..j]) 表示子数组arr[i..j] 中的最小值。如果数组的长度为N,要求时间复杂度是 O(N)。

  【解析】

  使用双端队列,qmax维护着窗口子数组arr[i..j]的最大值更新的结构,qmin维护着窗口子数组arr[i..j]的最小值更新的结构,所有下标值最多进qmax和qmin 一次,出qmax和qmin 一次,i 和j 的值也不断增加,从不减小,所以时间复杂度是O(N)。

  通过题目可以分析得到以下两个结论:

  1)如果子数组arr[i..j]满足条件,即max(arr[i..j])-min(arr[i..j])<=num,那么arr[k..l](i<=k<=l<=j)肯定都满足条件,即若一个数组满足条件,它的所有子数组肯定满足条件。

  2)如果子数组arr[i..j]不满足条件,即max(arr[i..j])-min(arr[i..j])>num,那么arr[k..l](k<=i<=j<=l)肯定不满足条件,即若一个数组不满足条件,所有包含它的数组肯定都不满足条件。

  

package com.test;

import java.util.LinkedList;

/**
 * Created by Demrystv.
 *
 * 所有下标值最多进qmax和qmin 一次,出qmax和qmin 一次,i 和j 的值也不断增加,从不减小,所以时间复杂度是O(N)
 */
public class GetNum {
    public int getNum(int[] arr, int num){
        if (arr.length==0 || arr==null){
            return 0;
        }

        //双端队列,qmax维护着窗口子数组arr[i..j]的最大值更新的结构,qmin维护着窗口子数组arr[i..j]的最小值更新的结构,

        //若某个数组满足条件,那么它所包含的子数组肯定都满足条件
        //若某数组不满足条件,那么包含它的所有数组肯定不满足条件
        LinkedList<Integer> qmax = new LinkedList<Integer>();
        LinkedList<Integer> qmin = new LinkedList<Integer>();
        int i = 0;
        int j = 0;
        int res = 0;
        while (i<arr.length){
            while (j<arr.length){
                while (!qmin.isEmpty() && arr[qmin.peekLast()]>= arr[j]){
                    qmin.pollLast();
                }
                qmin.addLast(j);

                while (!qmax.isEmpty() && arr[qmax.peekLast()]<= arr[j]){
                    qmax.pollLast();
                }
                qmax.addLast(j);

                if (arr[qmax.getFirst()] - arr[qmin.getFirst()] > num){
                    break;
                }

                j++;
            }

            //双端队列的队头到了起始点,就将他弹出来
            if (qmin.peekFirst() == i){
                qmin.pollFirst();
            }
            if (qmax.peekFirst() == i){
                qmax.pollFirst();
            }

            //利用的结论是 若arr[i..j]满足条件,那么arr[i..j-1]必定满足条件;若arr[i..j]满足条件,那么包含arr[i..j]的数组必定不满足条件
            res += j - i;
            i++;
        }
        return res;
    }
}

原文地址:https://www.cnblogs.com/Demrystv/p/9302388.html

时间: 2024-07-31 12:47:28

栈和队列----最大值减去最小值小于等于num的子数组的数量的相关文章

[程序员代码面试指南]栈和队列-最大值减去最小值 小于或等于num 的子数组的数量(双端队列)

题目 给定数组arr和整数num,求数组的子数组中有多少个的满足"最大值减去最小值<=num". 解题思路 分析题目,有结论: 如果数组arr[i...j]满足条件,则它的每一个子数组都满足条件. 如果数组arr[i...j]不满足条件,则包含它的每一个数组都不满足条件. 数据结构:用i.j表示当前窗口,分别使用两个双端队列维护窗口的最大值和最小值. 具体地,每次更新两个双端队列,检查当前的窗口是否满足条件,满足则j++,不满足则cnt+=j-i,更新双端队列,i++,j不变.若

【队列】最大值减去最小值小于等于num的子数组数量

摘自<程序员代码面试指南> 题目: 给定数组 arr 和整数 num, 共返回有多少个?数组满?如下情况:max(arr[i...j]) - min(arr[i...j]) <= nummax(arr[i...j])表示?数组 arr[i...j]中的最?值,min(arr[i...j])表示?数组arr[i...j]中的最小值. 题解: 区间最大最小值,立刻联想到单调栈(双端队列),不过稍微麻烦一些,需要在此基础上总结一些规律. 如果?数组 arr[i..j]满?条件, 即 max(a

最大值减去最小值小于或等于num的子数组数量

[说明]: 本文是左程云老师所著的<程序员面试代码指南>第一章中“最大值减去最小值小于或等于num的子数组数量”这一题目的C++复现. 本文只包含问题描述.C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书. 感谢左程云老师的支持. [题目]: 给定数组 arr 和整数 num,共返回多少个字数组满足如下情况: max(arr[i...j]) - min(arr[i...j]) <= num max(arr[i...j]) 表示字数组 arr[i...j] 中的最大

左神算法书籍《程序员代码面试指南》——1_10最大值减去最小值小于或等于num的子数组数量

[题目]给定数组arr和整数num,共返回有多少个子数组满足如下情况:max(arr[i.j]) - min(arr[i.j]) <= num max(arfi.j])表示子数组ar[ij]中的最大值,min(arli.j])表示子数组arr[i.j]中的最小值.[要求]如果数组长度为N,请实现时间复杂度为O(N)的解法.[题解]使用两个单调栈,一个栈维持从大到小的排序,头部永远是最大值一个维持从小到大的排序,头部永远都是最小值然后使用窗口进行数据移动当右移后,最大最小差超过num时,计算这段数

1.10 最大值减去最小值小于或等于num的子数组数量

[题目]: 给定数组arr和整数num,共返回有多少个子数组满足如下情况: max(arr[i...j] - min(arr[i...j]) <= num max(arr[i...j])表示子数组arr[i...j]中的最大值,min(arr[i...j])表示子数组arr[i...j]中的最小值 [要求]: 如果数组长度为N,请实现时间复杂度为O(N)的解法 原文地址:https://www.cnblogs.com/latup/p/9908350.html

算法总结之 最大值减去最小值或等于num的子数组数量

给定数组arr和整数num,共返回有多少个子数组满足  <= num 数组长度N    时间复杂度O(N) package TT; import java.util.LinkedList; public class Test127 { public int getNum(int[] arr, int num){ if(arr==null || arr.length == 0){ return 0; } LinkedList<Integer> qmin = new LinkedList&l

求数组所有区间最大值减去最小值之差的和(贝壳笔试题)

这个题直接暴力求解的话时间复杂度肯定是不行的,所以,我们要计算每个数值的贡献,对每一个数求他当最小值当了多少次,当最大值当了多少次,最后当最大值的次数乘以这个数值减去当最小值的次数乘以数值就得到这个数的贡献,依次把这n个数的贡献加起来就是整个极差之和. 在计算一个数当了多少最值的时候,我们要理解问题,因为区间是连续的,所以,以最小值为例,如果一个数是当前这段区间的最小值,那么他一定是当前这段区间最小的(这不废话),所以,我们就找到他往左做多能找到多少个连续的数都比他大,记录这个位置,同理找他右边

POJ 3264 Balanced Lineup【线段树区间查询求最大值和最小值】

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 53703   Accepted: 25237 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh

算法-栈,队列

常见的栈与队列算法题 1.使用队列实现栈 2.使用栈实现队列 3.包含最小值函数的栈 4.合法的出栈序列 5.简单计算器 1.队列实现栈 class MyStack { public: /** Initialize your data structure here. */ MyStack() { } /** Push element x onto stack. */ void push(int x) { int len=data.size(); data.push(x); while(len>0