简体   繁体   中英

Recursive Way to Find 2nd/3rd Smallest Element In Array

Below is a code I written to find the smallest element of an unsorted array in C++.

How should I go about editing my recursive function to find the second or even the third smallest element in the array?

I understand there are other methods out there (I've searched), however I'd like to know how to do it using a recursive function like this which works for just the minimum number.

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;
    }
}

Many thanks in advance

Here is my attempt at finding the 2nd smallest:

#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;
        }     
    }
}

Is there any reason you can not use std::sort(vector.beigin(), vector.end()) ? Then vector[0] is smallest, vector[1] is second smallest, and so on....

This is a function which will find the n smallest elements in a recursive way, hope it helps!

#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;
    }
}

Brief explanation: Get up to n smallest elements in ascending order from the left & right half, call them leftResult and rightResult , then merge the two, always picking the next smallest element from the two partial results. This is like merge sort , except that it will only return up to n elements instead of sorting the whole array.

Even though you divide the array in two halves in each step, you searching is still linear (since your data is unsorted). What about giving the function the last minimum?

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;
}

Then you can write a function that prints n smallest elements:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM