Pregunta

I'm reading Accelerated C++. At the moment I'm at the end of chapter 3 and here's the exercise that I'm trying to do:

"Write a program to compute and print the quartiles of a set of integers."

I found the first and the second quartiles, but I have no idea how to find the third. Here's my code:

 #include <algorithm>
 #include <iostream>
 #include <vector>
 using namespace std;

 int main(){
    cout<<"Enter numbers:";
    int x;
    vector<int>integers;
    while(cin>>x)
        integers.push_back(x);

    typedef vector<int>::size_type vec_sz;
    vec_sz size = integers.size();
    sort(integers.begin(), integers.end());
    vec_sz mid = size/2;
    vec_sz q1 = mid/2;
    double median;
    median = size % 2 == 0 ? ((double)integers[mid] + (double)integers[mid-1]) / 2
: integers[mid];
    double quartOne = ((double)integers[q1] + (double)integers[q1-1])/2; 
    cout<<"The First Quartile is: "<<quartOne<<endl;
    cout<<"The Second Quartile is: "<<median<<endl;
    return 0;
}
¿Fue útil?

Solución

One way would be to sort the collection and then take the 3 dividing items:

vector<int> v = ...;
sort(v.begin(), v.end());
int q12 = v[v.size()*1/4];
int q23 = v[v.size()*2/4];
int q34 = v[v.size()*3/4];

This is O(nlogn) in the number of data items.

Another way would be to perform a binary search of the data for the three divisions seperately. ie propose an initial q12, check if it is correct by making a pass of the data, if it is incorrect adjust it up or down by half, and repeat. Do likewise for q23 and q34.

This is technically O(n) because a 32-bit int has a fixed range and can be binary searched in 32 passes max.

Otros consejos

This solutions implements the second method described in wikipedia for computing quartiles. It provides the correct values both for vectors with odd and even lengths.

#include <vector>
#include <tuple>
#include <iostream>
using namespace std;

double median(vector<double>::const_iterator begin,
              vector<double>::const_iterator end) {
    int len = end - begin;
    auto it = begin + len / 2;
    double m = *it;
    if ((len % 2) == 0) m = (m + *(--it)) / 2;
    return m;
}

tuple<double, double, double> quartiles(const vector<double>& v) {
    auto it_second_half = v.cbegin() + v.size() / 2;
    auto it_first_half = it_second_half;
    if ((v.size() % 2) == 0) --it_first_half;

    double q1 = median(v.begin(), it_first_half);
    double q2 = median(v.begin(), v.end());
    double q3 = median(it_second_half, v.end());
    return make_tuple(q1, q2, q3);
}

int main() {
    vector<double> v = {2, 2, 3, 4, 4, 5, 5, 10};
    auto q = quartiles(v);
    cout << get<0>(q) << "," << get<1>(q) << "," << get<2>(q) << endl;
    return 0;
}

It is designed for real numbers, but it is easily adaptable for integer values (just round the values to their nearest integer).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top