我尝试编写一个从用户5
整数接收的程序并打印第二个最小数字。
以下是我尝试过的示例:
#include <iostream>
using namespace std;
int main () {
int a,b,c,d,e;
cin>>a>>b>>c>>d>>e;
if (a>b && a<c && a<d && a<e)
cout<<a<<endl;
if (b>a && b<c && b<d && b<e)
cout<<b<<endl;
if (c>a && c<b && c<d && c<e)
cout<<c<<endl;
if (d>a && d<b && d<c && d<e)
cout <<d<<endl;
if (e>a && e<b && e<c && e<d)
cout <<e<<endl;
return 0;
}
当我输入1 2 3 4 5
时,它会打印第二个最小值,但是当我输入
时
5 4 3 2 1
屏幕上不会打印任何内容。我做错了什么?还有其他方法来编写我的程序吗?
答案 0 :(得分:4)
您对逻辑的问题在于,您不强制自己只打印1个项目,至少打印一个项目。 使用&#39; else&#39; if / else语法的一部分,您将确保只能命中一个分支。然后,您可以在最后使用其他内容进行跟进,因为您知道所有其他条件都是错误的。
完成此操作后,您将看到您打印的最后一个值,(1)而不是预期的(4)。这是因为你关于如何找到第二低的逻辑是错误的。对于案例5,4 ...
,b> a是假的注意: 每个受雇的工程师都会在std :: vector / std :: array中创建一个循环,我建议你将老师指向这篇文章,因为鼓励循环是一件好事而不是坏事。
像
这样的东西vector<int> data;
for (int i=0; i<5; ++i) {
int t;
cin >> t;
data.push_back(t);
}
std::nth_element(data.begin(), data.begin()+1, data.end(), std::greater<int>());
cout << data[1];
答案 1 :(得分:3)
5个元素有120种可能的排列。您的代码应输出所有这些代码的正确数字。因此,一个傻瓜式的代码将使用120次重复检查,如下所示:
if (a > b && b > c && c > d && d > e) // the order is a>b>c>d>e
cout << d;
else if (a > b && b > c && c > e && e > d) // the order is a>b>c>e>d
cout << e;
...
else if (e > d && d > c && c > a && e > b) // the order is e>d>c>a>b
cout << a;
else // the order is e>d>c>b>a
cout << b;
这是一个非常长,低效且棘手的代码。如果你只在一个变量中输入拼写错误,它会在极少数情况下输出错误的答案。此外,它无法处理某些输入相等的可能性。
如果排序算法的输入数是已知的小常数,则可以使用名为sorting networks的方法。这是一个定义明确的计算机科学问题,它为少量输入提供了众所周知的最优解决方案,而且肯定很小。用于5个输入的最佳分类网络包含9个比较器,并且例如描述了这些比较器。 here
由于您不需要对数字进行排序,只知道第二个最小的输入,您可以进一步减小网络的大小,为7个比较器。
完整的排序网络(没有从9减少到7)转换为C ++:
if (b < c)
swap(b, c);
if (d < e)
swap(d, e);
if (b < d)
swap(b, d);
if (a < c)
swap(a, c);
if (c < e)
swap(c, e);
if (a < d)
swap(a, d);
if (a < b)
swap(a, b);
if (c < d)
swap(c, d);
if (b < c)
swap(b, c);
// now the order is a ≥ b ≥ c ≥ d ≥ e
cout << d;
这段代码也很模糊 - 根本不明显它是如何以及为什么有效 - 但至少它很小并且在某种意义上是最佳的。此外,很明显它总是打印一些东西(因此它解决了原始问题)并支持部分相等输入的情况。
如果您在较大的项目中使用此类代码,则应记录从中获取该代码的位置并对其进行测试。幸运的是,有120种不同的可能性(或32,如果你使用的话 zero-one principle),因此有一种方法可以证明此代码没有错误。
答案 2 :(得分:2)
这对你有用。 (请注意,它可能不是最好的方法,您可以通过计算min和secondMin的函数来最小化它,而不是逻辑的丑陋复制粘贴,但它会让您开始:
#include <iostream>
using namespace std;
int main () {
int a,b,c,d,e;
int min, secondMin;
cin>>a>>b;
min = a < b ? a : b;
secondMin = a < b ? b : a;
cin>>c;
if (c < min)
{
secondMin = min;
min = c;
}
else if (c < secondMin)
{
secondMin = c;
}
cin>>d;
if (d < min)
{
secondMin = min;
min = d;
}
else if (c < secondMin)
{
secondMin = d;
}
cin>>e;
if (e < min)
{
secondMin = min;
min = e;
}
else if (e < secondMin)
{
secondMin = e;
}
cout << "min = " << min << ", secondMin = " << secondMin << endl;
return 0;
}
如果您有任何问题,请随时在评论中提问
答案 3 :(得分:2)
#include <set>
std::set<int> values = { a, b, c, d, e }; // not an array.
int second_min = *std::next(values.begin(), 1); // not a loop
答案 4 :(得分:1)
递归和更通用方法怎么样? 没有数组,没有循环,并且不仅限于5个整数。
以下函数get_2nd_min()
跟踪从std::cin
读取的总共count
次的两个最低整数:
#include <climits>
#include <cstddef>
#include <iostream>
int get_2nd_min(size_t count, int min = INT_MAX, int second_min = INT_MAX)
{
if (!count)
return second_min; // end of recursion
// read next value from cin
int value;
std::cin >> value;
// Does second_min need to be updated?
if (value < second_min) {
// Does min also need to be updated?
if (value < min) {
// new min found
second_min = min; // move the so far min to second_min
min = value; // update the new min
} else {
// value is lower than second_min but higher than min
second_min = value; // new second_min found, update it
}
}
// perform recursion
return get_2nd_min(count - 1, min, second_min);
}
为了读取5个整数并获得第二个最低值:
int second_min = get_2nd_min(5);
答案 5 :(得分:0)
<强>更新强> 在此解决方案中,我使用 min 函数:
#include <iostream>
using namespace std;
int minDifferentFromFirstMin(int x, int y, int firstMin) {
if(x < y) {
if(x != firstMin) {
return x;
}
else {
return y;
}
}
if(y < x) {
if(y != firstMin) {
return y;
}
else {
return x;
}
}
//if x & y are equals, return one of them
return x;
}
int main () {
int a,b,c,d,e;
int iter11, iter12, iter13;
int iter21, iter22, iter23;
int firstMinimum, secondMinimum;
cin>>a>>b>>c>>d>>e;
//iteration 1: find the first minimum
iter11 = min(a, b);
iter12 = min(c, d);
iter13 = min(iter11, iter12);
firstMinimum = min(iter13, e);
//iteration 2: find the second minimum
iter21 = minDifferentFromFirstMin(a, b, firstMinimum);
iter22 = minDifferentFromFirstMin(c, d, firstMinimum);
iter23 = minDifferentFromFirstMin(iter21, iter22, firstMinimum);
secondMinimum = minDifferentFromFirstMin(iter23, e, firstMinimum);
cout<<secondMinimum<<endl;
}
答案 6 :(得分:0)
一种方法是首先找到最小数字min
,然后找到不是min
的最小值。要做到这一点,首先要找到最小值:
int min = std::min(a, std::min(b, std::min(c, std::min(d, e))));
现在我们需要再次执行相同操作,但忽略min
。我们可以使用一个名为triMin
的函数来执行此操作,该函数接受3个值并丢弃任何最小值:
int triMin(int currentMin, int left, int right)
{
if(currentMin == left) return right;
if(currentMin == right) return left;
return std::min(left, right);
}
您现在可以将它们组合起来得到答案:
int a = 5, b = 4, c = 3, d = 2, e = 1;
int min = std::min(a, std::min(b, std::min(c, std::min(d, e))));
int min2 = triMin(min, a, triMin(min, b, triMin(min, c, triMin(min, d, e))));
std::cout << "Second min = " << min2 << std::endl;
这会打印2
答案 7 :(得分:0)
可以使用one-pass算法来完成此任务。不需要使用任何集合(数组,集合或任何东西) 这种一次通过算法具有内存效率 - 它不需要将所有元素存储在集合中(并浪费内存),并且当其他解决方案因内存不足而失败时,甚至可以使用大量元素。 这个算法的一般想法是这样的:
minimum
和second minimum
个数字。minumum
对其进行测试,以确定它是否为新的最小号码。
minimum
,请将旧最小值存储在second minimum
数字second minimum
个数字。
second minimum
号码。second minimum
号码包含所有已见号码的答案。调查所有数字后second minimum
都包含答案
这是使用c ++ 17(link to wandbox):
#include <iostream>
#include <optional>
int main()
{
int a, b, c, d, e;
std::cin >> a >> b >> c >> d >> e;
// you can find second minimal number while going through each number once
auto find_current_answer = [minimum = std::optional<int>{}, next_to_minimum = std::optional<int>{}](int next) mutable {
// when receiving next number
// 1. check if it is new minimum
if (!minimum || minimum > next) {
// move values like this: next_to_minimum <- minimum <- next
next_to_minimum = std::exchange(minimum, next);
}
// 2. else check if it is new next_to_minimum
else if (!next_to_minimum || next_to_minimum > next) {
next_to_minimum = next;
}
// 3. return current answer
return next_to_minimum;
};
// repeat as much as you like
find_current_answer(a);
find_current_answer(b);
find_current_answer(c);
find_current_answer(d);
// store answer that is interesting to you
auto result = find_current_answer(e);
// if it has value - it is the answer
if (result) {
std::cout << "Answer: " << *result << '\n';
}
else {
std::cout << "Not enough numbers!\n";
}
}