2015-09-04 2 views
-1

Моя программа должна подсчитать, сколько раз данные в моем массиве менялись от увеличения до уменьшения или наоборот. Например: {1,2,3,4,3,4} изменяется дважды по мере увеличения первых четырех элементов, затем уменьшается o 3 (вызывает одно изменение), а затем увеличивается до четырех, вызывая второе изменение. Идея в моем коде заключалась в том, что каждый раз, когда большее или уменьшенное значение изменено на false, оно будет учитываться, когда это произойдет, но я не могу заставить его работать. Любая помощь очень ценится, поскольку я действительно борюсь с этим!C++ подсчитывает, сколько раз данные в массиве меняли направления?

unsigned count = 0; 
bool greater = true; 
bool decrease = true; 
for (unsigned i = 0; i < elements; i++){ 
    if (a[i + 1] > a[i]){ 
     greater = true; 
    } 
    else 
     greater = false; 
    count++; 
} 
for (unsigned i = 0; i < elements; i++){ 
    if (a[i + 1] < a[i]){ 
     decrease = true; 
    } 
    else 
     decrease = false; 
    count++; 
} 
     return count; 
+0

Try разбив сложную задачу на более мелкие легче проблем. например можете ли вы построить новый массив 'bool', чьи записи сообщают вам, увеличивается или уменьшается исходный массив? Если бы у вас был такой массив, не могли бы вы решить проблему? – Hurkyl

ответ

1

Вы должны изменить свои циклы. Прежде всего, вы должны остановить цикл с размером-1. Потому что вы сравниваете со следующим элементом, и вы можете выйти за пределы, если ваш for работает до тех пор, пока элементы вместо элементов-1.

Кроме того, у вас есть логическая проблема. Если вы используете логическую переменную как флаг, вы должны проверить, истинно это или нет, прежде чем увеличивать счетчик. И если вы увеличиваете счетчик, вы должны сбросить этот флаг. Нечто похожее на нисходящую петлю должно работать. Возможно, есть небольшая ошибка, потому что у меня нет никого, чтобы проверить ее сейчас. Но это должно быть что-то похожее на это.

for (unsigned i = 0; i < elements-1; i++){ 
    if (a[i + 1] > a[i]){ 
     greater = true; 
    } 
    else{ 
     greater = false; 
    } 
    if(greater){ 
     count++; 
     greater = false; 
    } 
} 
+1

К сожалению, это не сработало, так как при вводе массива, такого как {1,2,3,4,5}, программа выводит, что она изменилась 4 раза, но мы хотим ее, когда она изменяется от увеличения к уменьшению или наоборот от слева направо справа от значений. – Beezy

+0

В этом случае вы должны изменить условия if. Но, по крайней мере, измените заголовок для заголовка, потому что вы можете свернуть свое приложение;) – acostela

2

Ваша логика неправильно

вы можете сделать что-то вроде

enum class EDirection { none, decreasing, increasing}; 

std::size_t count_direction_changes(const std::vector<int>& v) 
{ 
    std::size_t res = 0; 
    EDirection direction = EDirection::none; 

    for (std::size_t i = 1; i != v.size(); ++i) { 
     const int diff = v[i] - v[i - 1]; 
     switch (direction) 
     { 
      case EDirection::none: { 
       if (diff == 0) { 
        break; 
       } 
       direction = (diff > 0) ? EDirection::increasing : EDirection::decreasing; 
       break; 
      } 
      case EDirection::increasing: { 
       if (diff < 0) { 
        ++res; 
        direction = EDirection::decreasing; 
       } 
       break; 
      } 
      case EDirection::decreasing: { 
       if (diff > 0) { 
        ++res; 
        direction = EDirection::increasing; 
       } 
       break; 
      } 
     } 
    } 
    return res; 
} 

Demo

+0

это работает только с классами, или вы можете записать его как обычные функции? – Beezy

+0

Не уверен, что вы имеете в виду ... Это уже свободная функция. вы можете изменить 'std :: vector' на другой * диапазон *. – Jarod42

0

Это очень похоже на Jarod42, но, видя, как я уже закодированы он будет бросать это там. BTW, я использую немного неудобно v[n] < v[n - 1], поэтому необходимо применить operator<, чтобы применить алгоритм к пользовательскому типу (то есть не operator>).

#include <iostream> 
#include <vector> 

template <typename T> 
size_t changes(const std::vector<T>& v) 
{ 
    if (v.size() <= 2) return 0; 
    size_t count = 0; 
    enum { Increasing, Decreasing, Flat } last; 
    last = v[0] < v[1] ? Increasing : v[1] < v[0] ? Decreasing : Flat; 
    for (size_t i = 2; i < v.size(); ++i) 
     if (v[i - 1] < v[i]) 
     { 
      if (last == Decreasing) ++count; 
      last = Increasing; 
     } 
     else if (v[i] < v[i - 1]) 
     { 
      if (last == Increasing) ++count; 
      last = Decreasing; 
     } 
    return count; 
} 

int main() 
{ 
    std::cout << changes<int>({ 1, 3, 5, 4, 6 }) << '\n'; 
    std::cout << changes<int>({ 3, 3, 5, 4, 6 }) << '\n'; 
    std::cout << changes<int>({ 4, 3, 5, 4, 2, 2, 1 }) << '\n'; 
} 

Просмотреть пробел here.

0

Вот другой подход, похожий на Тони и Джерода:

#include <vector> 
#include <cassert> 
#include <iostream> 

size_t countTrendChanges(const std::vector<int>& a) { 
    if (a.size() < 3) 
    return 0; 

    int trend = 0; 
    size_t count = 0; 
    for (size_t i = 1; i != a.size(); ++i) { 
    int new_trend = (a[i-1] < a[i]) - (a[i] < a[i-1]); 
    if (new_trend == 0) 
     continue; 
    if (trend != 0 && new_trend != trend) 
     count++; 
    trend = new_trend; 
    } 
    return count; 
} 

int main() { 
assert(countTrendChanges({}) == 0); 
assert(countTrendChanges({1}) == 0); 
assert(countTrendChanges({3,2,1}) == 0); 
assert(countTrendChanges({1,2,3}) == 0); 
assert(countTrendChanges({1,2,2,3}) == 0); 
assert(countTrendChanges({3,2,1,2,3}) == 1); 
assert(countTrendChanges({1,2,3,2}) == 1); 
assert(countTrendChanges({2,1,1,2}) == 1); 
assert(countTrendChanges({1,2,2,1}) == 1); 
assert(countTrendChanges({1,2,3,4,3,4}) == 2); 
} 
Смежные вопросы