Search code examples
arrayscmaxmin

Determine the three maximum and two minimum values of the array


Task:

Given a natural number N (set arbitrarily as a preprocessor constant) and one-dimensional array A0, A1, …, AN-1 of integers (generate positive and negative elements randomly, using the <stdlib.h> library function rand()). Perform the following actions: Determine the three maximum and two minimum values of this array.

Code with search for two minimum values:

#include <stdio.h>
#include <stdlib.h>

#define N 9

int main() {
    int M[N], i, a[N], fbig, sbig, tbig, min, smin;
    for (i = 0; i < N; i++) {
        M[i] = rand() % 20 - 10;
        printf("%i\t", M[i]);
    }
    printf("\n");
    for (i = 0; i < N; i++) {
        if (a[i] < min) {
            smin = min;
            min = a[i];
        } else
        if (a[i] < smin && a[i] != min)
            smin = a[1];
    }            
    printf("\nMinimum=%d \nSecond Minimum=%d", min, smin);
    
    return 0;
}

I tried to compare array elements with each other but here is my result:

-7  -4  7   5   3   5   -4  2   -1  

Minimum=0 
Second Minimum=0

I would be very grateful if you could help me fix my code or maybe I'm doing everything wrong and you know how to do it right. Thank you for your time


Solution

  • I will revise my answer if op address what to do about duplicate values. My answer assume you want possible duplicate values in the minimum and maximum arrays, while other answers assume you want unique values.

    The easiest solution would be to sort the input array. The minimum is the first 2 values and the maximum would be the last 3:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define MAX_N 3
    #define MIN_N 2
    #define N 9
    
    void generate(size_t n, int a[n]) {
        for(size_t i = 0; i < n; i++)
            a[i] = rand() % 20 - 10;
    }
    
    void print(size_t n, int a[n]) {
        for(size_t i = 0; i < n - 1; i++)
            printf("%d, ", a[i]);
        if(n) printf("%d\n", a[n-1]);
    }
    
    int cmp_asc(const void *a, const void *b) {
        if(*(int *) a < *(int *) b) return -1;
        if(*(int *) a > *(int *) b) return 1;
        return 0;
    }
    
    int main() {
        int t = time(0);
        srand(t);
        printf("%d\n", t); // essential for debugging
    
        int a[N];
        generate(N, a);
        print(N, a);
    
        qsort(a, N, sizeof *a, cmp_asc);
        print(MIN_N, a);
        print(MAX_N, a + (N - MAX_N));
    }
    

    If you cannot use sort then consider the following purpose built algorithm. It's much easier to use arrays (min and max) rather than individual values, and as a bonus this allows you to easily change how many minimum (MIN_N) and maximum (MAX_N) values you want. First we need to initialize the min and max arrays, and I use the initial values of the input array for that. I used a single loop for that. To maintain the invariant that the min array has the MIN_N smallest numbers we have seen so far (a[0] through a[i-1]) we have to replace() largest (extrema) of them if the new value a[i] is smaller. For example, if the array is min = { 1, 10 } and the value we are looking at is a[i] = 5 then we have to replace the 10 not the 1.

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define MAX_N 3
    #define MIN_N 2
    #define N 9
    
    void generate(size_t n, int a[n]) {
        for(size_t i = 0; i < n; i++)
            a[i] = rand() % 20 - 10;
    }
    
    void print(size_t n, int a[n]) {
        for(size_t i = 0; i < n - 1; i++)
            printf("%d, ", a[i]);
        if(n) printf("%d\n", a[n-1]);
    }
    
    int cmp_asc(const void *a, const void *b) {
        if(*(int *) a < *(int *) b) return -1;
        if(*(int *) a > *(int *) b) return 1;
        return 0;
    }
    
    int cmp_desc(const void *a, const void *b) {
        return cmp_asc(b, a);
    }
    
    void replace(size_t n, int a[n], int v, int (*cmp)(const void *, const void *)) {
        int *extrema = &a[0];
        for(size_t i = 1; i < n; i++) {
            if(cmp(extrema, &a[i]) < 0) {
                extrema = &a[i];
            }
        }
        if(cmp(extrema, &v) > 0)
            *extrema = v;
    }
    
    void min_max(size_t n, int a[n], size_t min_n, int min[n], size_t max_n, int max[n]) {
        for(size_t i = 1; i < n; i++) {
            if(i < min_n)
                min[i] = a[i];
            else
                replace(min_n, min, a[i], cmp_asc);
            if(i < max_n)
                max[i] = a[i];
            else
                replace(max_n, max, a[i], cmp_desc);
        }
    }
    
    int main() {
        int t = time(0);
        srand(t);
        printf("%d\n", t); // essential for debugging
    
        int a[N];
        generate(N, a);
        print(N, a);
    
        int min[MIN_N];
        int max[MAX_N];
        min_max(N, a, MIN_N, min, MAX_N, max);
        print(MIN_N, min);
        print(MAX_N, max);
    }
    
    

    and here is example output. The first value is a the seed in case you have to reproduce a run later. Followed by input, min and max values:

    1674335494
    -7, 0, -2, 7, -3, 4, 5, -8, -9
    -9, -8
    7, 5, 4
    

    If MIN_N or MAX_N gets large, say, ~1,000+, then you want sort the min and max arrays and use binary search to figure out where to inserta[i]. Or use a priority queue like a heap instead of arrays.