最大波动

试题编号: 201609-1
试题名称: 最大波动
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  小明正在利用股票的波动程度来研究股票。小明拿到了一只股票每天收盘时的价格,他想知道,这只股票连续几天的最大波动值是多少,即在这几天中某天收盘价格与前一天收盘价格之差的绝对值最大是多少。

输入格式
  输入的第一行包含了一个整数n,表示小明拿到的收盘价格的连续天数。
  第二行包含n个正整数,依次表示每天的收盘价格。

输出格式
  输出一个整数,表示这只股票这n天中的最大波动值。

样例输入
6
2 5 5 7 3 5
样例输出
4

样例说明
  第四天和第五天之间的波动最大,波动值为|3-7|=4。
评测用例规模与约定
  对于所有评测用例,2 ≤ n ≤ 1000。股票每一天的价格为1到10000之间的整数。

代码:

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;

int main(){
	int n , number;
	vector<int> vc , rst;
	while(cin >> n){
		for(int i = 0 ; i < n ; i++){
			cin >> number;
			vc.push_back(number);
		}
		int temp = vc[0];
		for(int i = 1 ; i < vc.size() ; i++){
			int r = abs(temp - vc[i]);
			temp = vc[i];
			rst.push_back(r);
		}
		sort(rst.begin() , rst.end());
		cout << rst[rst.size() - 1] << endl;
		vc.clear();
		rst.clear();
	}
    return 0;
}

/*测试用例 

6
2 5 5 7 3 5

*/


C++中解决最大波动类问题,通常可以采用以下几种常见方法: ### 暴力枚举法 暴力枚举法是最直观的方法,通过遍历所有可能的子区间,计算每个子区间的波动值,然后找出最大波动值。 ```cpp #include <iostream> #include <vector> #include <algorithm> int maxFluctuation(const std::vector<int>& arr) { int n = arr.size(); int maxFluc = 0; for (int i = 0; i < n; ++i) { for (int j = i; j < n; ++j) { int maxVal = *std::max_element(arr.begin() + i, arr.begin() + j + 1); int minVal = *std::min_element(arr.begin() + i, arr.begin() + j + 1); maxFluc = std::max(maxFluc, maxVal - minVal); } } return maxFluc; } int main() { std::vector<int> arr = {1, 3, 2, 5, 4}; std::cout << "Max fluctuation: " << maxFluctuation(arr) << std::endl; return 0; } ``` 这种方法的时间复杂度为$O(n^2)$,因为需要两层嵌套循环来遍历所有子区间,对于大规模数据效率较低。 ### 动态规划法 动态规划法可以通过记录一些中间结果来避免重复计算,提高效率。对于最大波动问题,可以维护两个数组,分别记录以每个位置结尾的子数组的最大值和最小值。 ```cpp #include <iostream> #include <vector> #include <algorithm> int maxFluctuation(const std::vector<int>& arr) { int n = arr.size(); if (n == 0) return 0; std::vector<int> maxEndingHere(n); std::vector<int> minEndingHere(n); maxEndingHere[0] = minEndingHere[0] = arr[0]; int maxFluc = 0; for (int i = 1; i < n; ++i) { maxEndingHere[i] = std::max(maxEndingHere[i - 1], arr[i]); minEndingHere[i] = std::min(minEndingHere[i - 1], arr[i]); maxFluc = std::max(maxFluc, maxEndingHere[i] - minEndingHere[i]); } return maxFluc; } int main() { std::vector<int> arr = {1, 3, 2, 5, 4}; std::cout << "Max fluctuation: " << maxFluctuation(arr) << std::endl; return 0; } ``` 动态规划法的时间复杂度为$O(n)$,因为只需要遍历一次数组,空间复杂度为$O(n)$,主要用于存储中间结果数组。 ### 单调栈法 单调栈可以用来在$O(n)$时间复杂度内解决一些最大波动相关问题,特别是在需要找到每个元素左右两侧第一个比它大或小的元素的情况下。 ```cpp #include <iostream> #include <vector> #include <stack> #include <algorithm> int maxFluctuation(const std::vector<int>& arr) { int n = arr.size(); std::vector<int> leftMin(n), rightMin(n), leftMax(n), rightMax(n); std::stack<int> s; // 计算每个元素左侧第一个比它小的元素的位置 for (int i = 0; i < n; ++i) { while (!s.empty() && arr[s.top()] >= arr[i]) s.pop(); leftMin[i] = s.empty() ? -1 : s.top(); s.push(i); } while (!s.empty()) s.pop(); // 计算每个元素右侧第一个比它小的元素的位置 for (int i = n - 1; i >= 0; --i) { while (!s.empty() && arr[s.top()] >= arr[i]) s.pop(); rightMin[i] = s.empty() ? n : s.top(); s.push(i); } while (!s.empty()) s.pop(); // 计算每个元素左侧第一个比它大的元素的位置 for (int i = 0; i < n; ++i) { while (!s.empty() && arr[s.top()] <= arr[i]) s.pop(); leftMax[i] = s.empty() ? -1 : s.top(); s.push(i); } while (!s.empty()) s.pop(); // 计算每个元素右侧第一个比它大的元素的位置 for (int i = n - 1; i >= 0; --i) { while (!s.empty() && arr[s.top()] <= arr[i]) s.pop(); rightMax[i] = s.empty() ? n : s.top(); s.push(i); } int maxFluc = 0; for (int i = 0; i < n; ++i) { int left = leftMin[i] == -1 ? 0 : arr[leftMin[i]]; int right = rightMax[i] == n ? 0 : arr[rightMax[i]]; maxFluc = std::max(maxFluc, std::max(arr[i] - left, right - arr[i])); } return maxFluc; } int main() { std::vector<int> arr = {1, 3, 2, 5, 4}; std::cout << "Max fluctuation: " << maxFluctuation(arr) << std::endl; return 0; } ``` 单调栈法的时间复杂度为$O(n)$,因为每个元素最多入栈和出栈一次,空间复杂度也为$O(n)$,主要用于存储左右边界信息。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值