【JAVA】求数组连续区间内最大值与最小值的差不大于K的最大区间长度 Pro20210705
题目
假设会提供某家公司N天期间的股票价格。你偶尔会用过去的股票价格进行模拟投资,但是股票价格的剧烈波动会使你感到不安,所以你想了解股票价格在什么时间段内几乎保持不变。这里的价格几乎不变,表示的是在一段时间内的股票最大值和最小值之差为小于给出的K值。
例如,如上一样给出过去10天的股票价格以及K=10的情况,可以说明除了股票价格为15的最后一天之外,其他9天内的价格几乎没有变化。(前9天的最大值为13,最小值为3,二者之差为10,这满足K=10。但在第10天,股票价格为15,其与跟最小值3的差为12,这超过了 K=10。)另外,9天是股票价格几乎没有变化的最长持续时间。
编写一个程序,计算出在给定期间内股票最大值与最小值之差小于K的最长持续时间。
[限制条件]
1.天数N为介于1到300,000之间的整数。
2.股票价格为介于1到1,000,000,000之间的整数。
3.最小值与最大值之差K为介于1到1,000,000,000之间的整数。
[输入]
第一行给出测试用例数量T。接着给出T个测试用例。各测试用例的第一行空格区分给出总天数N和K。下一行空格区分按时间由远至近的顺序依次给出N天的股票价格。
[输出]
各测试用例的答案按照顺序标准输出。对于每个用例输出“#x”(x 为测试用例编号,从1 开始),加一个空格(不包含引号),输出题目中要求的满足条件的最长持续时间长度(天数)。
[输入输出 示例]
(输入)
3
10 10
17 25 22 15 18 18 21 12 5 25
10 10
8 11 3 10 11 7 7 13 10 15
1 1
1000000000
(输出)
#1 7
#2 9
#3 1
方法一:双指针+优先级队列
思路:
既然是连续区间,那么在下标left和下标right区间内,元素都是计算范围内的,所以用双指针指定连续区间即可;
最大值和最小值的获取,可以使用一个降序优先级队列和一个升序优先级队列;
步骤1:初始化 left = right = 0;且将Data[0]放入PQ1和PQ2;
步骤2:从两个PQ中获取极值min、max,若极值对应的下标,不在[left, right]范围内,则该极值已失效,扔掉重新获取;
步骤3:若max - min > K,则left++,然后重复步骤2和步骤3;若max - min <= K,则局部最优解ASW = right - left +1,然后right++,同时将Data[right]放入PQ1和PQ2,再重复步骤2和步骤3;
最终,当right右移至Data[N-1],计算结束,ASW即为所求。
时间复杂度:NlogN(实际为NlogN)
空间复杂度:N(实际为2N)
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
static class Node {
int idx, value;
public Node(int i, int v) {
this.idx = i;
this.value = v;
}
}
public static void main(String[] args) throws IOException {
System.setIn(new FileInputStream("D:\\SW\\TestCase\\sample_input_20210705.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int T = Integer.parseInt(st.nextToken());
for (int test_case = 1; test_case <= T; test_case++) {
st = new StringTokenizer