构建最大二叉树
总提交数: 216次通过数: 56次通过率: 25.93%
内存限制: 10485760(BYTE)时间限制: 40(MS)输入限制: 1000(行)输出限制: 1000(行)
题目描述
给定一个不重复的非空整数数组。 最大二叉树 可以用下面的算法从给定数组递归地构建:
- 创建一个根节点,其值为数组中的最大值。
- 递归地在最大值 左边 的 子数组前缀上 构建左子树。
- 递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 最大二叉树 的层序遍历结果 。
样例输入输出
样例1
输入:
3 2 1 6 0 5
输出:
6 3 5 2 0 1
递归调用如下所示:
- [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5] 。
- [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。
- 空数组,无子节点。
- [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1] 。
- 空数组,无子节点。
- 只有一个元素,所以子节点是一个值为 1 的节点。
- [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 [] 。
- 只有一个元素,所以子节点是一个值为 0 的节点。
- 空数组,无子节点。
#include<iostream>
#include<string>
#include <sstream>
#include <vector>
#include<queue>
using namespace std;
struct Node {
int value;
Node* left;
Node* right;
};
class BinaryTree {
public:
Node* treenode;
BinaryTree(string input) {
vector<int>nums;
istringstream iss(input);
int num;
while (iss >> num) { // 从字符串流中提取整数
nums.push_back(num); // 将整数添加到vector中
}
treenode = MaxBinaryTree(nums, 0, nums.size() - 1);
}
Node* MaxBinaryTree(vector<int>nums,int start,int end) {
if (start > end)return nullptr;
int maxpos = start;
for (int i = start; i <= end ; i++) {
if (nums[maxpos] < nums[i]) {
maxpos = i;
}
}
Node* node = new Node;
node->value = nums[maxpos];
node->left = MaxBinaryTree(nums, start, maxpos - 1);
node->right = MaxBinaryTree(nums, maxpos+1, end);
return node;
}
void PrintTree() {
queue<Node*>q;
q.push(treenode);
while (!q.empty()) {
cout << q.front()->value<<' ';
if(q.front()->left!=nullptr)q.push(q.front()->left);
if(q.front()->right!=nullptr)q.push(q.front()->right);
q.pop();
}
}
};
int main() {
string input;
getline(cin, input);
BinaryTree tree(input);
tree.PrintTree();
}
逆序交易对
总提交数: 125次通过数: 45次通过率: 36.00%
内存限制: 10485760(BYTE)时间限制: 20(MS)输入限制: 1000(行)输出限制: 1000(行)
题目描述
在股票交易的分析中,逆势交易是一种常用的投资策略,旨在与市场主流趋势相反的策略进行投资。基于这种投资策略,金融分析师需要关注股价突然下降的时刻。为了有效追踪这些情况,我们定义了股市逆序交易对的概念,即某日股价高于其后某日的股价就构成一个逆序交易对。给定一个整型数组 prices,其中每个元素代表一天的股票收盘价,请设计程序,用分治算法计算数组内所有逆序交易对的总数。
输入格式:
共两行,输入一个整数 n,代表整型数组prices数组的长度;第二行为prices数组,用空格分割
输出格式:
输出一个整数,表示逆序交易对的个数
提示:尝试使用归并排序的思路求解
样例输入输出
样例1
输入:
5
9 7 5 4 6
输出:
8
// 该样例中的逆序交易对为:
// (9, 7), (9, 5), (9, 4), (9, 6), (7, 5), (7, 4), (7, 6), (5, 4)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 辅助函数,用于合并两个已排序的子序列并计算逆序对
pair<int, vector<int>> mergeAndCountInv(vector<int>& left, vector<int>& right) {
int inv_count = 0;
vector<int> merged;
merged.reserve(left.size() + right.size());
auto left_it = left.begin();
auto right_it = right.begin();
while (left_it != left.end() && right_it != right.end()) {
if (*left_it > *right_it) {
// 计算逆序对数量
inv_count += distance(left_it, left.end());
merged.push_back(*right_it++);
}
else {
merged.push_back(*left_it++);
}
}//这个过程顺便排序
// 合并剩余部分
merged.insert(merged.end(), left_it, left.end());
merged.insert(merged.end(), right_it, right.end());
return make_pair(inv_count, merged);
}
// 分治计算逆序交易对数量
int countInversions(vector<int>& prices) {
if (prices.size() <= 1) {
return 0;
}
int mid = prices.size() / 2;
vector<int> left(prices.begin(), prices.begin() + mid);
vector<int> right(prices.begin() + mid, prices.end());
// 递归计算左右子序列的逆序对数量
int count1 = countInversions(left);
int count2 = countInversions(right);
// 合并子序列并计算跨子序列的逆序对数量
pair<int, vector<int>> merge_result = mergeAndCountInv(left, right);
int count3 = merge_result.first;
prices = merge_result.second;
return count1 + count2 + count3;
}
int main() {
int n;
cin >> n;
vector<int> prices(n);
for (int i = 0; i < n; ++i) {
cin >> prices[i];
}
// 计算逆序交易对数量
int inversion_count = countInversions(prices);
// 输出逆序交易对数量
cout << inversion_count << endl;
return 0;
}