【发布时间】:2022-01-20 06:56:12
【问题描述】:
给定的问题是: 给出了许多自然数“N”。半运算减去集合中最大的元素,将其分成两个相等的部分,然后将两个结果数返回给集合。任务是在半运算被应用“n”次时找到集合中的最大数。
输入格式
对于标准输入的每个例子都给出:“N”集合中数字的个数,以及元素的倍数“n”;
约束
0
输出: 分数或整数。
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cassert>
using namespace std;
class Fraction{
public:
Fraction(int t) : top(t), bottom(1) {}
Fraction(int t, int b) : top(t), bottom(b)
{
normalize();
}
int numerator() const
{
return top;
}
int denominator() const
{
return bottom;
}
int compare(const Fraction& right) const
{
return numerator() * right.denominator() - denominator() * right.numerator();
}
private:
void normalize()
{
int sign = 1;
if(top < 0)
{
sign = -1;
top = -top;
}
if(bottom < 0)
{
sign = -1;
bottom = -bottom;
}
assert(bottom != 0);
int d = 1;
if(top > 0) d = gcd(top, bottom);
top = sign *(top / d);
bottom = bottom / d;
}
int gcd(int n, int m)
{
assert(n > 0 && m > 0);
while(n!=m)
{
if(n < m)
m -= n;
else
n -= m;
}
return n;
}
int top;
int bottom;
};
Fraction operator/(const Fraction& left, const Fraction& right)
{
Fraction result(left.numerator() * right.denominator(),
left.denominator() * right.numerator());
return result;
}
bool operator<(const Fraction& left, const Fraction& right)
{
return left.compare(right) < 0;
}
ostream& operator<<(ostream& out, const Fraction& value)
{
if(value.denominator() != 1)
out << value.numerator() << "/" << value.denominator();
else
out << value.numerator();
return out;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N,n;
while(cin >> N && cin >> n)
{
vector<Fraction> vec;
for(int i = 0; i < N; i++)
{
int value;
cin >> value;
vec.push_back(value);
}
for(int i = 0; i < n; i++)
{
Fraction temp = *max_element(vec.begin(), vec.end()) / 2;
int maxIndex = distance(vec.begin(), max_element(vec.begin(), vec.end()));
vec[maxIndex] = temp;
vec.push_back(temp);
}
cout << *max_element(vec.begin(), vec.end())<< endl;
}
return 0;
}
代码确实有效,但我的问题是由于hackerrank超时而终止 我也尝试过对其进行排序并处理最后一个元素,但它甚至比 max_element 还要慢。我正在寻找一种方法来优化我的代码或一种完全不同的方法的想法。
这里也是 make_heap 的实现,但它经历了 800 次迭代,它让我超时(应该能够处理 2000000)
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N,n;
while(cin >> N && cin >> n)
{
vector<Fraction> vec;
for(int i = 0; i < N; i++)
{
int value;
cin >> value;
vec.push_back(value);
}
make_heap(vec.begin(),vec.end());
for(int i = 0; i < n; i++)
{
cout << "was here: " << i << endl;
vec.push_back(vec.front() / 2); push_heap(vec.begin(),vec.end());
vec.push_back(vec.front() / 2); push_heap(vec.begin(),vec.end());
pop_heap(vec.begin(),vec.end()); vec.pop_back();
}
cout<< vec.front() << '\n';
}
return 0;
}
也用 priority_queue 尝试过,它也有 736 次迭代,然后由于超时而终止
int main() {
int N,n;
while(cin >> N && cin >> n)
{
priority_queue<Fraction> frac;
for(int i = 0; i < N; i++)
{
int value;
cin >> value;
frac.push(value);
}
for(int i = 0; i < n; i++)
{
Fraction temp = frac.top() / 2;
frac.pop();
frac.push(temp);
frac.push(temp);
}
cout << frac.top() << endl;
}
return 0;
}
如果有人想知道这是解决方案:
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N,n;
while(cin >> N && cin >> n)
{
vector<pair<Fraction, int>> vec;
for(int i = 0; i < N; i++)
{
int value;
cin >> value;
vec.push_back(make_pair(value,1));
}
sort(vec.begin(),vec.end());
while(vec.back().second <= n)
{
n -= vec.back().second;
pair<Fraction,int> temp(vec.back().first / 2, vec.back().second * 2);
vec.pop_back();
vec.push_back(temp);
sort(vec.begin(),vec.end());
}
cout << vec.back().first << endl;
}
return 0;
}
【问题讨论】:
-
代码中没有任何可以加速的东西。如有疑问,请尝试排序。
-
尝试排序在时间上是最糟糕的。
-
这个想法不是每次都对数组进行完全排序。您可以尝试使用最大堆。
-
@Damien 我尝试使用 make_heap 但它经历了大约 763 次(应该能够进行 2000000 次)迭代,然后给了我超时,所以我想它也没有那么快。
-
这是学习如何使用分析器的绝佳借口。找出瓶颈实际上在哪里。快速浏览一下,您无需每次迭代调用
max_element两次。