C++搜索数组中最大的数字

C++ searching for biggest numbers in array

本文关键字:数字 搜索 数组 C++      更新时间:2023-10-16

我需要从实际索引开始计算左边和右边数组中的最大数字。我的意思是如果我的阵列是

1, 3, 2, 4, 3;

我需要输出:

//Left Right
1 4 //no bigger on left, so 1; the biggest on right is 4
3 4 //and so on with rest points
3 4
4 4
4 3

我需要很快做到这一点,所以先左后右是个坏主意。我决定只在右边找到最大的,然后当我到达那里时,数下一个,以此类推。左边是最大的,如果实际的比它大,就改变它。但有些东西不起作用。。。程序有时输出错误。不幸的是,我不知道它的输入是什么。。。

这是我的代码,如果你能看到任何一般或算法错误,我很高兴你能发布它…

#include <cstdlib>
#include <iostream>
using namespace std;
inline int findmax(int tab[], int beg, int end)
{
    int max=0;
    for (int j=beg; j<end; j++)
        if (tab[j]>max) max=j;
    return max;
}
int main(int argc, char *argv[])
{
    int len;
    cin>>len;
    int h[len];
    for (int i=0; i<len; i++)
    cin>>h[i];
    int maxl=0, maxr;
    maxr=findmax(h,0,len);
    for (int i=0; i<len; i++)
    {
        if (h[i]>h[maxl]) maxl=i;
        if (i>maxr) maxr=findmax(h,i,len);
        cout<<h[maxl]<<" "<<h[maxr]<<endl;
    }
    //system("pause");
    return 0;
}

编辑:我已经阅读了所有的回复并实现了它。一个问题是我无法将值存储在第一个循环中,所以我必须将两者"合并"为。。。这是我现在的代码:

#include <cstdlib>
#include <iostream>
using namespace std;
inline int findmax(int tab[], int beg, int end)
{
    int max=0;
    for (int j=beg; j<end; j++)
        if (tab[j]>max) max=j;
    return max;
}
int main(int argc, char *argv[])
{
    int len;
    cin>>len;
    int h[len];
    int l[len];
    for (int i=0; i<len; i++)
    cin>>h[i];
    int maxl=0, maxr;
    maxr=len-1;
    for (int i=len-1; i>=0; i--)
    {
        if (h[i]>h[maxr]) maxr=i;
        l[i]=h[maxr];
    }
    for (int i=0; i<len; i++)
    {
        if (h[i]>h[maxl]) maxl=i;
        cout<<h[maxl]<<" "<<l[i]<<endl;
    }
    //system("pause");
    return 0;
}

由于嵌套循环,您的程序具有O(n^2)时间复杂性。但这可以在线性时间内完成:

您已经知道如何在每个元素的左边找到最大的元素:遍历所有元素,跟踪当前的最大值。每个元素左边最大的元素是到达该元素时的当前最大值。

要在每个元素的右边找到最大的元素,可以反向执行相同的操作:从右到左迭代数组,跟踪当前的最大值。

因此,您会有两个循环(从左到右和从右到左),但它们不会嵌套在一起,因此大型阵列的性能会更好。

使用std::max_element和std::count。或者将std::for_each与自定义类一起使用,自己查找索引。


inline int findmax(int tab[], int beg, int end)
{
    int max=0;
    for (int j=beg; j<end; j++)
        if (tab[j]>max) max=j;
    return max;
}

如果数组中的所有元素都为负数,则无效。使用std::numeric_limits<int>::min()作为初始值。

为了解决程序不工作的问题:findmax()返回一个存储在maxr中的值,但随后使用maxr作为索引,因此应该有一个函数来返回最大值的索引,而不是值。

Edit(正如barnes53所指出的):实际上,在findmax()函数中,max被用作索引和值。至少"if(tab[j]>max)max=j;"必须是"if(tab[j]>tab[max])max=j;"。如果这个函数被调用findIndexOfMax(),它会对我有所帮助。

对公认答案的改进:

你可以通过半途而废来消除至少25%(可能50%)的比较。

从左边开始,边走边计算"左边最大值"。从右边开始,边走边计算"右边的最大值"。

在中间汇合后,将汇合点的左最大值与右最大值进行比较。如果它们相等,那么你就知道其余计算的答案(你已经节省了50%的计算)。如果它们不相等,那么你必须在两半中最大值较大的一边继续计算,直到你在那一边达到最大值,然后你就知道了那一边其余部分的答案。

下面是interjay所说的实现:

#include <iostream>
#include <limits.h>
#define LENGTH 5
int h[LENGTH] = {1, 3, 2, 4, 3};
int maxl[LENGTH], maxr[LENGTH];
int main(int argc, char **argv)
{
    int max = INT_MIN;
    for(int i = 0; i < LENGTH; i++)
    {
        if (h[i] > max){ max = h[i]; }
        maxl[i] = max;
    }
    # Left to right, computer maxl
    max = INT_MIN;
    for(int i = LENGTH-1; i >= 0; i--)
    {
        if (h[i] > max){ max = h[i]; }
        maxr[i] = max;
    }
    # Right to left, computing maxr
    for (int i = 0; i < LENGTH; i++)
    {
        std::cout << maxl[i] << " " << maxr[i] << std::endl;
    }
    return 0;
}

听起来你的记忆力有限。在这种情况下,如果只将第一个和第三个循环组合在一起,在计算最大值时打印最大值,就可以去掉maxl数组。如果不清楚该怎么做,请告诉我。

stefaanv(近似地)确定了您的问题,所以我只展示一个不是O(n^2)的实现。

编辑:为了最小内存使用

#include <iostream>
#include <array>
#include <algorithm>
int main()
{
    std::array<int,5> input = {1, 3, 2, 4, 3}; // max_right
    std::array<int,5> max_left;
    max_left[0] = input[0];
    for(int i=1;i<input.size();++i) {
        max_left[i] = std::max(max_left[i-1],input[i]);
    }
    for(int i=input.size()-2;i>=0;--i) {
        input[i] = std::max(input[i+1],input[i]);
    }
    for(int i=0;i<input.size();++i) {
        std::cout << max_left[i] << ' ' << input[i] << 'n';
    }
}