NKUSOFT 算法导论上机作业2

构建最大二叉树

总提交数: 216次通过数: 56次通过率: 25.93%

内存限制: 10485760(BYTE)时间限制: 40(MS)输入限制: 1000()输出限制: 1000()

题目描述

给定一个不重复的非空整数数组。 最大二叉树 可以用下面的算法从给定数组递归地构建:

  1. 创建一个根节点,其值为数组中的最大值。
  2. 递归地在最大值 左边 的 子数组前缀上 构建左子树。
  3. 递归地在最大值 右边 的 子数组后缀上 构建右子树。

返回 最大二叉树 的层序遍历结果 


 

样例输入输出

样例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;
}

  • 14
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值