【问题标题】:Recursive Way to Find 2nd/3rd Smallest Element In Array在数组中查找第 2/3 个最小元素的递归方法
【发布时间】:2013-04-28 20:27:56
【问题描述】:

下面是我编写的用于在 C++ 中查找未排序数组的最小元素的代码。

我应该如何编辑我的递归函数以找到数组中第二甚至第三小的元素?

我知道还有其他方法(我已经搜索过),但是我想知道如何使用像这样的递归函数来做到这一点,它只适用于最小数量。

int min(vector<int> &array, int &min, int &next_min, int left,int right)
{    
    int a;        
    int b;

    if(left == right) { 
        return array[left];
    } else {   
        int mid= (right+left)/2;

        a = min(array,left,mid);
        b = min(array,mid+1,right);

        if (a<b) 
            return b;
        else         
            return a;
    }
}

在此先感谢

这是我寻找第二小的尝试:

#include<iostream>
#include<vector>
#include <cstdlib>

using namespace std;

int counter=0;

void minf(vector<int> &array,int left,int right,int &min, int &next_min);

int main()
{
    int next_min;

    cout << "Enter integers one line at a time. (Enter -999 to terminate)" << endl;

    vector<int> array;  // 
    int input;

    while(true){
        cin >> input;
        if(input == -999) //check for termination condition
        break;
        array.push_back(input);
    }

    int imin;
    int imax;

    cout<<"Enter imin, then imax"<<endl;
    cin>>imin;
    cin>>imax; 

    cout<<"Min number is " << next_min <<endl;

    cin.get();
    system("pause");
    return 0;
}

void minf(vector<int> &array,int left,int right,int &min, int &next_min)
{
    int a;
    int b;
    int c;
    int d;

    if(left == right) { 
        min = array[left];
        next_min = 2147483647;
    } else {
        int mid= (right+left)/2;

        minf(array,left,mid,a,b);
        minf(array,mid+1,right,c,d);

        if (a < b && a < c && a < d) {
            min = a;
            if (b<c && b <d)
                next_min = b;
            else if (c < b && c < d)
                next_min = c;
            else
                next_min = d;
        }    

        if (b < a && b < c && b < d){
            min = b;
            if (a<c && a <d)
                next_min = a;
            else if (c < b && c < d)
                next_min = c;
            else
                next_min = d;
        }

        if (c < a && c < b && c < d) {
            min = c;
            if (b<a && b<d)
                next_min = b;
            else if (a < b && a < d)
                next_min = a;
            else
                next_min = d;
        }   

        if (d < a && d < c && d < b){
            min = d;
            if (a<c && a <b)
                next_min = a;
            else if (c < b && c < a)
                next_min = c;
            else
                next_min = b;
        }     
    }
}

【问题讨论】:

  • 不是让你的函数返回最小的元素,你需要让它返回前 n 个最小的元素。
  • 嗨,我不太清楚你的意思。你能再解释一下吗?谢谢
  • 这个问题不适合递归解决方案,特别是因为迭代解决方案已经在 O(n) 时达到最优。这种递归要求是不切实际的。关闭主题,因为 SO 是针对实际编程问题,而不是理论问题。
  • 现在,min 返回一个具有最小值的单个 int。为了概括您的算法,您需要让它返回一个具有前 n 个最小值的整数向量。其余大部分逻辑都是一样的。
  • @VaughnCato 我明白了。谢谢,我试试看!

标签: c++ arrays recursion


【解决方案1】:

你有什么理由不能使用std::sort(vector.beigin(), vector.end())?那么vector[0] 是最小的,vector[1] 是第二小的,以此类推....

【讨论】:

  • 啊,我没有任何理由不能。但是,我将在几天后参加考试,并且我认为有一个巨大的暗示,我们可能会在编写递归函数以严格在未排序的数组上找到第二个最小元素时进行测试。因此,我试图事先弄清楚这一点
  • 恕我直言,这不是理解/使用递归函数的最佳问题陈述。尝试使用递归和非递归解决Tower of Hanoii 问题:)
【解决方案2】:

这是一个以递归方式查找n最小元素的函数,希望对您有所帮助!

#include <vector>
#include <iostream>

using namespace std;

vector<int> nMin(const vector<int> &array, int n, int left, int right) {
    vector<int> result;
    if (left == right) {
        result.push_back(array[left]);
    } else {
        int mid = (right + left) / 2;
        vector<int> leftResult = nMin(array, n, left, mid);
        vector<int> rightResult = nMin(array, n, mid + 1, right);
        int i = 0;
        int l = 0;
        int r = 0;
        int L = leftResult.size();
        int R = rightResult.size();
        while (i < n && (l < L || r < R)) {
            i++;
            if (l < L) {
                if (r < R) {
                    if (leftResult[l] < rightResult[r]) {
                        result.push_back(leftResult[l++]);
                    } else {
                        result.push_back(rightResult[r++]);
                    }
                } else {
                    result.push_back(leftResult[l++]);
                }
            } else {
                result.push_back(rightResult[r++]);
            }
        }
    }
    return result;
}

int main() {
    vector<int> test = {-2, 6, 7, 1, 3, 7, 4, 2, 5, 0, 8, -2};
    vector<int> smallest3 = nMin(test, 3, 0, test.size() - 1);
    for (int num : smallest3) {
        cout << num << endl;
    }
}

简要说明:从左半边和右半边升序获取n最小的元素,称它们为leftResultrightResult,然后将两者合并,总是从两个部分结果中挑选下一个最小的元素.这类似于merge sort,只是它只会返回最多n 个元素,而不是对整个数组进行排序。

【讨论】:

  • 感谢您的帮助。不过,我刚刚意识到,如果数组中有两个相似的数字,例如{1 , 1 , 3 , 4} ,搜索第二个最小值也会给出 1 而不是 3。
【解决方案3】:

即使您在每个步骤中将数组分成两半,您的搜索仍然是线性的(因为您的数据未排序)。给函数最后一个最小值怎么样?

int minf(vector<int> &array, int last_min)
{
    int minimum = 2147483647;
    for (vector<int>::iterator it = array.begin(); it != array.end(); ++it)
        if(*it < minimum && *it > last_min) minimum = *it;
    return minimum;
}

然后你可以写一个打印n个最小元素的函数:

void printMins(vector<int> &array, int count)
{
    int last_min = -2147483648;
    while(count-- > 0)
    {
        last_min = minf(array, last_min);
        cout << last_min << endl;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 2014-12-07
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    • 1970-01-01
    相关资源
    最近更新 更多