【JAVA】求数组连续区间内最大值与最小值的差不大于K的最大区间长度 Pro20210705 (双指针+优先级队列 / 双指针+IndexTree)

给定一段时间内的股票价格,找到价格差不超过K的最大连续天数。双指针结合优先级队列或IndexTree的方法分别实现,求解最长稳定时间段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【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(br.readLine());

			int N = Integer.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值