【问题标题】:Find the biggest 3 numbers in a vector找出向量中最大的 3 个数字
【发布时间】:2010-11-08 18:34:13
【问题描述】:

我正在尝试创建一个函数来获取向量中的 3 个最大数字。例如: 数字:1 6 2 5 3 7 4 结果:5 6 7

我想我可以对它们进行 DESC 排序,在开始时获取 3 个数字,然后再使用 ASC,但这会浪费内存分配和执行时间。我知道有一个更简单的解决方案,但我无法弄清楚。另一个问题是,如果我只有两个数字怎么办...

顺便说一句:我使用 BorlandC++ 3.1 作为编译器(我知道,很老,但那是我将在考试中使用的......)

谢谢大家。

LE:如果有人想了解更多关于我要完成的工作,您可以查看代码:

#include<fstream.h>
#include<conio.h>

int v[1000], n;
ifstream f("bac.in");

void citire();
void afisare_a();
int ultima_cifra(int nr);
void sortare(int asc);

void main() {
    clrscr();
    citire();
    sortare(2);
    afisare_a();
    getch();
}

void citire() {
    f>>n;
    for(int i = 0; i < n; i++)
        f>>v[i];
        f.close();
}                            

void afisare_a() {
    for(int i = 0;i < n; i++)
            if(ultima_cifra(v[i]) == 5)
            cout<<v[i]<<" ";
}

int ultima_cifra(int nr) {
    return nr - 10 * ( nr / 10 );
}

void sortare(int asc) {
    int aux, s;
        if(asc == 1)
        do {
            s = 0;
            for(int i = 0; i < n-1; i++)
                if(v[i] > v[i+1]) {
                    aux = v[i];
                    v[i] = v[i+1];
                    v[i+1] = aux;
                    s = 1;
                }
        } while( s == 1);
    else
        do {
            s = 0;
            for(int i = 0; i < n-1; i++)
                if(v[i] < v[i+1]) {
                    aux = v[i];
                    v[i] = v[i+1];
                    v[i+1] = v[i];
                                        s = 1;
                }
                } while(s == 1);
}

城市 = 阅读 Afisare = 显示 Ultima Cifra = 数字的最后一位 Sortare = 冒泡排序

【问题讨论】:

  • 为什么要标记冒泡排序?
  • 出于好奇,那是什么考试?即使在大学,我们也可以使用当前的编译器。而且学习(通过考试)这些古老的技术听起来并不是很有用。 ;-)
  • 我真的很好奇你为什么要做两种?
  • 我已经编辑了这篇文章,所以你可以看到我为什么用冒泡排序来标记它。是的,这是一个大学考试,但罗马尼亚在考试中仍然使用纸而不是个人电脑......现在我在阅读回复后正在考虑,将它分类两次是无意义的。

标签: c++ vector c++builder


【解决方案1】:

如果您使用的是现代编译器,则可以使用std::nth_element 来查找前三个。照原样,您必须扫描数组,跟踪迄今为止在任何给定时间看到的三个最大元素,当您到达终点时,这些就是您的答案。

对于三个元素,管理起来很简单。如果您必须在 N 可能相当大的情况下执行 N 个最大(或最小)的元素,那么您几乎肯定会想要使用 Hoare 的 select 算法,就像 std::nth_element 所做的那样。

【讨论】:

  • 最佳 STL,也是非 STL 解决方案的最佳启发式
  • +1 因为它使用标准的 C++ 库,但对于提问者,我认为他不允许使用它,因为 Borland 3.1 是早期的,我认为是 90 年代早期。 :)
  • ...Turbo C++ 的美好时光(我相信是旧版本)
  • @nevets1219:有 Turbo C++ 1.0、Borland C++ 2.0、Borland C++ 3.0,然后是 Borland C++ 3.1。套用一句老话来说,Borland C++ 3.1 比它的前辈和继任者有了巨大的改进。
  • 嗯,我第一次学习 PHP,因为我是一个原生的 Web 开发人员,现在在 Borland C++ 上学习 C++ 真的很痛苦:(
【解决方案2】:

您可以在完全不需要排序的情况下执行此操作,它可以在 O(n) 时间内通过线性搜索和 3 个变量保持您的 3 个最大数字(或者如果该向量不会改变,则为您的最大数字的索引)。

【讨论】:

  • 这不适合后续问题“从 1000000 的列表中找出最大的 10000”
  • @Steve true,如果它变成了一个任意的“从 y 中找出前 x”的问题,那么我的解决方案将不合适,我会选择做类似你的事情。我特别想回答 Bdesign 的直接问题,即从(我假设的)有限列表中选择一个非常小的子集,而不必经过他模糊的双重排序。
  • 问题本身并不要求这样做,对于那种后续行动,您当然会以不同的方式处理它。目前,没有关于内存或速度要求的确切细节。
  • 这是评论,而不是反对票的理由。 @Jerry 的解决方案是最好的通用实现,你的最好原位
  • @Steve,我认为这是当之无愧的评论。我的解决方案突然出现在我的脑海中,因为它非常适合提问者的范围,并且可以解决他使用古老编译器的限制。我不会说我的答案是最好的 - 我从来没有这样做过,因为我永远无法确定其他人会出现并提出更好的建议。
【解决方案3】:

为什么不单步执行一次并跟踪遇到的最高 3 位数字?

编辑:输入的范围对于如何跟踪最高 3 位数字很重要。

【讨论】:

    【解决方案4】:

    使用std::partial_sort 对您关心的第一个c 元素进行降序排序。它将在给定数量的所需元素 (n log c) 时间内以线性时间运行。

    【讨论】:

    • 部分排序是最容易编码的,但 nth_element 和线性分区保持线性时间,而“x of y”问题的 partial_sort 是 Omega(ylogx) 时间。
    • @Neil G 这两种方法在容器中的元素数量上都是线性的,对于特定的期望数量的最高元素。你说得对,partial_sort 在许多情况下可以有稍高的C,但实际上这可能无关紧要。
    • 部分排序必须对 x 个元素进行排序,因此它具有额外的 log(x) 因子。考虑 x=y 的极限情况,部分排序在 xlogx 时间内运行,而 nth_element 解决方案在 x 时间内运行。但是,我之前错了,部分排序解的运行时间可能是 Omega(y + xlogx),所以如果 x 独立于 y,它与第 n 个元素的解是一样的。
    【解决方案5】:

    如果您不能使用 std::nth_element,请编写您自己的选择函数。

    你可以在这里阅读它们:http://en.wikipedia.org/wiki/Selection_algorithm#Selecting_k_smallest_or_largest_elements

    【讨论】:

      【解决方案6】:

      对它们进行正常排序,然后使用rbegin() 从后面迭代,尽可能多地提取(当然不超过rend())。

      sort 顺便说一句,无论是 ASC 还是 DESC 都会发生,因此内存不是问题,因为您的容器元素是 int,因此没有自己的封装内存要管理。

      【讨论】:

        【解决方案7】:

        是的,排序很好。 A 特别适用于长列表或可变长度列表。

        你为什么要排序两次呢?第二种可能实际上效率很低(取决于使用的算法)。反向会更快,但为什么还要这样做呢?如果您希望它们在最后按升序排列,则先将它们按升序排序(并从最后获取数字)

        【讨论】:

          【解决方案8】:

          我认为您可以选择在向量中扫描三个最大元素或对其进行排序(在向量中使用排序或将其复制到像集合这样的隐式排序容器中)。

          【讨论】:

            【解决方案9】:

            如果您可以控制数组填充,也许您可​​以添加排序的数字,然后选择前 3 个(即),否则您可以使用二叉树执行搜索,或者只使用 birryree 所说的线性搜索...

            【讨论】:

              【解决方案10】:

              感谢@nevets1219 指出下面的代码只处理正数。

              我还没有对这段代码进行足够的测试,但这是一个开始:

              #include <iostream>
              #include <vector>
              
              int main()
              {
                  std::vector<int> nums;
                  nums.push_back(1);
                  nums.push_back(6);
                  nums.push_back(2);
                  nums.push_back(5);
                  nums.push_back(3);
                  nums.push_back(7);
                  nums.push_back(4);
              
                  int first = 0;
                  int second = 0;
                  int third = 0;
              
                  for (int i = 0; i < nums.size(); i++)
                  {
                      if (nums.at(i) > first)
                      {
                          third = second;
                          second = first;            
                          first = nums.at(i);
                      }
                      else if (nums.at(i) > second)
                      {
                          third = second;
                          second = nums.at(i);
                      }
                      else if (nums.at(i) > third)
                      {
                          third = nums.at(i);
                      }
                      std::cout << "1st: " << first << " 2nd: " << second << " 3rd: " << third << std::endl;
              
                  }
              
                  return 0;
              }
              

              【讨论】:

              • 您可能需要包含一个注释,说明这只需要正的非零整数。如果允许零和负数,则需要额外的逻辑。您还需要将 cout 排除在循环之外。
              【解决方案11】:

              以下解决方案在 O(n) 中找到三个最大的数并保留它们的相对顺序:

              std::vector<int>::iterator p = std::max_element(vec.begin(), vec.end());
              int x = *p;
              *p = std::numeric_limits<int>::min();
              
              std::vector<int>::iterator q = std::max_element(vec.begin(), vec.end());
              int y = *q;
              *q = std::numeric_limits<int>::min();
              
              int z = *std::max_element(vec.begin(), vec.end());
              
              *q = y;   // restore original value
              *p = x;   // restore original value
              

              【讨论】:

                【解决方案12】:

                向量顶部N 元素的一般解决方案:

                1. 为您的顶部 N 元素创建一个长度为 N 的数组或向量 topElements
                2. topElements 的每个元素初始化为向量中第一个元素的值。
                3. 选择向量中的下一个元素,如果没有剩余元素,则结束。
                4. 如果所选元素大于topElements[0],则将topElements[0] 替换为元素的值。否则,执行3。
                5. i = 0 开始,如果topElements[i] 大于topElements[i + 1],则将topElements[i]topElements[i + 1] 交换。
                6. i 小于N 时,增加i 并转到5。
                7. 转到 3。

                这应该会导致topElements 包含您的顶部N 元素以相反的值顺序 - 也就是说,最大值在topElements[N - 1] 中。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-12-31
                  • 2017-04-12
                  • 2011-01-03
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多