左神算法课子数组最大差值小于某阈值,求满足条件的子数组个数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了左神算法课子数组最大差值小于某阈值,求满足条件的子数组个数相关的知识,希望对你有一定的参考价值。

题目描述:

  技术分享

解法思路:

   本题其实是滑动窗口的变形。主体思路为:

  1.从第一个元素开始依次向后遍历,同时维护两个窗口(由于要同时操作窗口的头部和尾部,故采用双端队列):

      最大值窗口(递减),头部永远存最大值

      最小值窗口(递增),头部永远存最小值

  2.比较两个窗口的头部元素差值,若差值大于阈值,即可跳出内循环。

  3.跳出内循环后,检查头部元素是否过期,若过期,则清除。

复杂度:

  时间复杂度:O(n),注意虽然是两层循环,但元素只从滑动窗口尾部进,从头部清除,只是顺序扫描了一遍。

  空间复杂度:O(n),这里利用两个滑动窗口分别保存最大值和最小值。

代码:

  1 //C++版,注释部分为调试用,可忽略
  2 #include <iostream>
  3 #include <vector>
  4 #include <deque>
  5 #include <stdlib.h>
  6 using namespace std;
  7 
  8 // void printArray(vector<int>& array) {
  9 //     if(array.empty()){
 10 //         cout<<"array is empty."<<endl;
 11 //         return ;
 12 //     }
 13 //     cout << array[0];
 14 //     for (int i = 1; i < array.size(); ++i)
 15 //         cout << " " << array[i];
 16 //     cout << endl;
 17 // }
 18 
 19 // void printDeque(deque<int>& de) {
 20 //     if(de.empty()){
 21 //         cout<<"deque is empty."<<endl;
 22 //         return ;
 23 //     }
 24 //     cout << de.at(0);
 25 //     for (int i = 1; i < de.size(); ++i)
 26 //         cout << " " << de.at(i);
 27 //     cout << endl;
 28 // }
 29 
 30 // vector<int> getRandomArray(int len) {
 31 //     if (len < 0) {
 32 //         exit(1) ;
 33 //     }
 34 //     vector<int> array(len);
 35 //     for (int i = 0; i < len; ++i) {
 36 //         array[i] = (int)(rand() % 10);
 37 //     }
 38 //     return array;
 39 // }
 40 
 41 int getNum(vector<int> arr, int num) {
 42     if (arr.empty()) {
 43         return 0;
 44     }
 45     deque<int> qmin;
 46     deque<int> qmax;
 47     int i = 0;
 48     int j = 0;
 49     int res = 0;
 50     while (i < arr.size()) {
 51         while (j < arr.size()) {
 52             while (!qmin.empty() && arr[qmin.back()] >= arr[j]) {
 53                 qmin.pop_back();//cout<<"qmin.pop_back();"<<endl;
 54             }
 55             qmin.push_back(j);//cout<<"qmin.push_back(j);"<<endl;
 56             while (!qmax.empty() && arr[qmax.back()] <= arr[j]) {
 57                 qmax.pop_back();//cout<<"qmin.pop_back();"<<endl;
 58             }
 59             qmax.push_back(j);//cout<<"qmax.push_back(j);"<<endl;
 60             if (arr[qmax.front()] - arr[qmin.front()] > num) {
 61                 break;
 62             }
 63             ++j;
 64             // cout << "------in-----" << endl;
 65             // printDeque(qmin);
 66             // printDeque(qmax);
 67             // cout << "-----------" << endl;
 68         }
 69         // cout << "-----out1------" << endl;
 70         // printDeque(qmin);
 71         // printDeque(qmax);
 72         // cout << "-----------" << endl;
 73 
 74         if (qmin.front() == i) {
 75             qmin.pop_front();
 76         }
 77         if (qmax.front() == i) {
 78             qmax.pop_front();
 79         }
 80 
 81         // cout << "-----out2------" << endl;
 82         // printDeque(qmin);
 83         // printDeque(qmax);
 84         // cout << "-----------" << endl;
 85 
 86         //cout << "j=" << j << "  i= " << i << endl;
 87         res += j - i;
 88         ++i;
 89     }
 90     return res;
 91 }
 92 
 93 int main() {
 94     // vector<int> arr=getRandomArray(20);
 95     vector<int> arr{1, 2, 4, 3, 0, 7}; //test
 96     int num = 5;
 97     // printArray(arr);
 98     cout << getNum(arr, num) << endl;
 99     return 0;
100 }

 

 1 //Java版,左神给的代码
 2 package problems_2017_08_16;
 3 
 4 import java.util.LinkedList;
 5 
 6 public class Problem_02_AllLessNumSubArray {
 7 
 8     public static int getNum(int[] arr, int num) {
 9         if (arr == null || arr.length == 0) {
10             return 0;
11         }
12         LinkedList<Integer> qmin = new LinkedList<Integer>();
13         LinkedList<Integer> qmax = new LinkedList<Integer>();
14         int i = 0;
15         int j = 0;
16         int res = 0;
17         while (i < arr.length) {
18             while (j < arr.length) {
19                 while (!qmin.isEmpty() && arr[qmin.peekLast()] >= arr[j]) {
20                     qmin.pollLast();
21                 }
22                 qmin.addLast(j);
23                 while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[j]) {
24                     qmax.pollLast();
25                 }
26                 qmax.addLast(j);
27                 if (arr[qmax.getFirst()] - arr[qmin.getFirst()] > num) {
28                     break;
29                 }
30                 j++;
31             }
32             if (qmin.peekFirst() == i) {
33                 qmin.pollFirst();
34             }
35             if (qmax.peekFirst() == i) {
36                 qmax.pollFirst();
37             }
38             res += j - i;
39             i++;
40         }
41         return res;
42     }
43 
44     // for test
45     public static int[] getRandomArray(int len) {
46         if (len < 0) {
47             return null;
48         }
49         int[] arr = new int[len];
50         for (int i = 0; i < len; i++) {
51             arr[i] = (int) (Math.random() * 10);
52         }
53         return arr;
54     }
55 
56     // for test
57     public static void printArray(int[] arr) {
58         if (arr != null) {
59             for (int i = 0; i < arr.length; i++) {
60                 System.out.print(arr[i] + " ");
61             }
62             System.out.println();
63         }
64     }
65 
66     public static void main(String[] args) {
67         int[] arr = getRandomArray(30);
68         int num = 5;
69         printArray(arr);
70         System.out.println(getNum(arr, num));
71 
72     }
73 
74 }

 

以上是关于左神算法课子数组最大差值小于某阈值,求满足条件的子数组个数的主要内容,如果未能解决你的问题,请参考以下文章

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

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

左神算法第八节课:介绍递归和动态规划(汉诺塔问题;打印字符串的全部子序列含空;打印字符串的全排列,无重复排列;母牛数量;递归栈;数组的最小路径和;数组累加和问题,一定条件下最大值问题(01背包))

左神算法进阶班5_3求公司的最大活跃度

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

h指数:求数组中满足有h个数>=h,n-h个数<=h的最大h