子数组的取值范围-贪心算法
2021/4/9 1:25:13
本文主要是介绍子数组的取值范围-贪心算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Description 给定数组arr和整数num,求arr的连续子数组中满足:其最大值减去最小值的结果大于num的个数。请实现一个时间复杂度为O(length(arr))的算法。 Input 输入第一行为测试用例个数。每一个用例有若干行,第一行为数组,每一个数用空格隔开,第二行为num。 Output 输出一个值。 Sample Input 1 1 3 6 4 3 2 2 Sample Output 1 6 解题思路: 最暴力方法可以找所有的子数组,然后判断差值是否超过num。 对于以i为起始点的子数组,如果(i-j)为存在差值超过num的最小范围,那么j之后的元素加到后面也一定满足条件。也就是数量为arr.size-j。 暴力方法可以遍历数组元素i,找到差值超过num的最小范围(i-j)。时间复杂度为O(n^2)。 要达到更小时间复杂度,可以使用双端队列。qmax和qmin存储以i为起始的子数组最大值和最小值。 算法步骤如下: 1.定义左指针l和右指针r,初始指向第一个元素,并将第一个元素加入qmax和qmin队列。 2.右指针右移一位,将右指针指向元素temp插入qmax和qmin尾部。对于qmax,如果尾部有元素比temp更小,则弹出;对于qmin,如果尾部有元素比temp更大,则弹出。 3.判断qmax和qmin首元素差值是否超过num。 超过则说明该窗口(l-r)达到满足条件的最小范围的以l起始的子数组,计算出size-r,然后将l指针右移动一位,同时判断qmax和qmin首元素是否是去除元素,是的话也要弹出。然后返回步骤3继续判断。 不超过的话则返回步骤2,直到r指针移动到数组末尾。 代码如下:1 import java.util.*; 2 3 public class Main { // 注意类名必须为Main 4 public static void main(String[] args) { 5 Scanner scan = new Scanner(System.in); 6 int number = Integer.parseInt(scan.nextLine()); 7 // number个测试样例 8 for (int k = 0; k < number; k++){ 9 // 输入数据 10 String str = scan.nextLine(); 11 int num = Integer.parseInt(scan.nextLine()); 12 String[] strs = str.split(" "); 13 int n = strs.length; 14 int[] arr = new int[n]; 15 for (int i = 0; i < n; i++) 16 arr[i] = Integer.parseInt(strs[i]); 17 // 特殊情况,num<0,所有子数组都满足条件 18 if (num < 0) { 19 System.out.println(n*(n+1)/2); 20 } else { 21 int sum = 0; 22 // 两个双端队列,存储窗口内最大值和最小值 23 LinkedList<Integer> qmax = new LinkedList<>(); 24 LinkedList<Integer> qmin = new LinkedList<>(); 25 int l = 0; 26 int r; 27 for (r = 0; r < n; r++) { 28 // 将第r个元素插入qmax 29 while (!qmax.isEmpty() && arr[r] > arr[qmax.getLast()]) 30 qmax.pollLast(); 31 qmax.addLast(r); 32 // 将第r个元素插入qmin 33 while (!qmin.isEmpty() && arr[r] < arr[qmin.getLast()]) 34 qmin.pollLast(); 35 qmin.addLast(r); 36 // 如果差值超过num 37 if (arr[qmax.getFirst()] - arr[qmin.getFirst()] > num) { 38 // 计算个数 39 sum += n-r; 40 // 将指针l指向的元素去除 41 if (l == qmax.getFirst()) 42 qmax.pollFirst(); 43 if (l == qmin.getFirst()) 44 qmin.pollFirst(); 45 // 左指针右移一格 46 l++; 47 // 右指针暂时保持不动 48 r--; 49 } 50 } 51 System.out.println(sum); 52 } 53 } 54 scan.close(); 55 } 56 57 }
这篇关于子数组的取值范围-贪心算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-11cursor试用出现:Too many free trial accounts used on this machine 的解决方法
- 2025-01-11百万架构师第十四课:源码分析:Spring 源码分析:深入分析IOC那些鲜为人知的细节|JavaGuide
- 2025-01-11不得不了解的高效AI办公工具API
- 2025-01-102025 蛇年,J 人直播带货内容审核团队必备的办公软件有哪 6 款?
- 2025-01-10高效运营背后的支柱:文档管理优化指南
- 2025-01-10年末压力山大?试试优化你的文档管理
- 2025-01-10跨部门协作中的进度追踪重要性解析
- 2025-01-10总结 JavaScript 中的变体函数调用方式
- 2025-01-10HR团队如何通过数据驱动提升管理效率?6个策略
- 2025-01-10WBS实战指南:如何一步步构建高效项目管理框架?