Home > database >  How to print the first and last element of the continuous part of an array?
How to print the first and last element of the continuous part of an array?

Time:04-29

Task description: In the input we have 6 days where we took measurements.

1st column is the morning measurements 2nd column is the evening measurements

we have to print the indexes (start and end) of the longest period where evening measurements were higher than morning measurements

I only want to print the indexes of the first and last element of an array where the array is continuous, for example:

The arr is {1, 6, 3, 4, 5}

the continuous elements are only: (3,4,5) and the first and last elements are -> (3,5)

#include <iostream>
    
using namespace std;
    
struct Measure {
    int morning, evening;
};


int main()
{
    Measure measures[300];

    int n, firstResult[100];
    cin >> n;
    for (int i = 0; i < n; i  ) {
        cin >> measures[i].morning >> measures[i].evening;
    }

    int counter = 0;
    for (int i = 0; i < n; i  ) {
        if (measures[i].morning < measures[i].evening) {
            counter  ;
            firstResult[counter] = i   1;

        }
    }

    for (int i = 1; i <= counter; i  ) {

                cout << firstResult[i] << " ";
       
    }

    cout << endl;

    return 0;
}

The input:

6
100 120
200 122
170 190
100 222
150 155
75 60

the output should be 3 and 5 because the array is continuous from the index 3rd to 5th but my code is giving 1 3 4 5 in output. How can I only print the first and last element of the continuous portion.

CodePudding user response:

I suggest to use hardcoded input rather than reading via cin for easier testing and debugging. And use std::vector for a dynamically sized array (= you don't know the size until runtime):

    std::stringstream ss{R"(100 120
                        200 122
                        170 190
                        100 222
                        150 155
                        75 60)"};
    std::vector<Measure> measures;
    Measure temp;
    while (ss >> temp.morning >> temp.evening) measures.push_back(temp);

Next you should actually find the contiguous sequences of elements. In your code you merely count all elements where morning < evening no matter where they are in the array. You can use a loop where you use a flag to remember if you are inside or outside a contiguous sequence. I strongly suggest to use 0-based indices always. If you are required to print 1-based indices as result you can still add one for the output.

std::vector<contiguous_sequence> find_contiguous_sequences(const std::vector<Measure>& m){
        std::vector<contiguous_sequence> result;
        contiguous_sequence current;
        bool inside = false;
        for (size_t i = 0; i < m.size();   i){
            if (m[i].morning < m[i].evening) {
                if (inside) continue;
                inside = true;                 // state change: outside -> inside       
                current.begin = i;
            } else {
                if (inside) {                  // state change: inside outside
                    current.end = i;
                    inside = false;
                    result.push_back(current);
                }
            }
        }
        if (inside) {                  // check if the last element of the array was inside
            current.end = m.size();
            result.push_back(current);
        }
        return result;            
}

Here inside keeps track of whether you are inside a sequnce of morning < evening elements. And begin and end of such sequences are stored in result. Note that I used to convention of half open intervals, ie begin is the first element in the sequence while end is one past the last element in the sequence. You need to consider this when there is a sequence at the end of the vector. Then the last end is not an element in the vector.

Calling this function with above input and printing its result:

    auto cs = find_contiguous_sequences(measures);

    for (const auto& e : cs ) std::cout << e.begin << " " << e.end << "\n";

results in

0 1
2 5

I'll leave it to you to find the largest sequence and print it.

Live Demo

CodePudding user response:

You have to remeber that you are inside a valid sequence and each time you enter a new valid sequence you have to reset your counter. Further you have to print just the forst and the last elements of the firstResult array. The code could be as below

#include <iostream>

using namespace std;

struct Measure {
    int morning, evening;
};


int main()
{
    Measure measures[300];

    int n, firstResult[100];
    cin >> n;
    for (int i = 0; i < n; i  ) {
        cin >> measures[i].morning >> measures[i].evening;
    }

    int counter = 0;
    bool counting = false;
    for (int i = 0; i < n; i  ) {
        if (measures[i].morning < measures[i].evening) 
        {
            if (!counting) {
                counting = true;
                counter = 0;
            }
            firstResult[counter  ] = i   1;

        }
        else
        {
            counting = false;
        }
    }

    if (counter > 0)
    {
        cout << firstResult[0] << " " << firstResult[counter - 1];
    }

    cout << endl;

    return 0;
}
  • Related