MAX значение матрицы и сохранение индексов в одном цикле - PullRequest
0 голосов
/ 29 ноября 2018

Я получаю матрицу размером NxM, и мне нужно найти максимальное значение, количество максимальных значений и строки, в которых оно содержится.Я устал использовать три для {для {}} циклов, но это заняло слишком много времени.Этот метод, кажется, работает для небольших входов, но когда я пробую его с матрицей 1000x1000, он завершается, прежде чем он даже принимает все входные данные.Я понимаю, что это может быть слишком много вопросов о noob, но я не мог найти ничего другого.

Вот мой код:

#include <iostream>
using namespace std;

int main()
{
    int n, m;
    int crnt{-51}, cnt{0};
    cin >> n >> m;
    int vekt[m];
    int lines[n];
    int inp;
    for(int i=0; i<n; i++)
    {
        for(int p=0; p<m; p++)
        {
            cin >> vekt[p];
        }
        for(int j=0; j<m; j++)
        {
            if(vekt[j] == crnt)
            {
                lines[cnt] = i + 1;
                cnt += 1;
            }
            if(vekt[j] > crnt)
            {
                crnt = vekt[j];
                lines[0] = i + 1;
                cnt = 1;
            }
        }
    }
    cout << cnt;
    for(int i=0; i<cnt; i++)
    {
        cout << " " << lines[i]; 
    }
    return 0;
}

РЕДАКТИРОВАТЬ: не использовать вектор или [n] былпросто проще ... я просто сохранил его в переменной и использовал bool:

int main()
{
    int n, m;
    int crnt{-51}, cnt{0};
    cin >> n >> m;
    int vekt[m];
    int lines[n];
    int inp;
    bool inLine;
    inLine = false;
    for(int i=0; i<n; i++)
    {

        inLine = false;
        for(int j=0; j<m; j++)
        {
            cin >> inp;
            if(inp == crnt && inLine == false)
            {
                lines[cnt] = i + 1;    
                cnt += 1;
                inLine = true;    
            }
            if(inp > crnt)
            {
                crnt = inp;
                lines[0] = i + 1;
                cnt = 1;
            }
        }
    }
    cout << cnt;
    for(int i=0; i<cnt; i++)
    {
        cout << " " << lines[i]; 
    }
    return 0;
}

Это сократило время на столько, что я перешел предел.

Ответы [ 3 ]

0 голосов
/ 29 ноября 2018

Проверьте эту реализацию, без STL и векторов:

 void input_matrix(int **&matrix, int &lines, int &columns)
 {
     int m = 0, n = 0;
     cout << "input lines count:";
     cin >> m;
     cout << "input rows count:";
     cin >> n;

     matrix = new int *[m];
     for(int i = 0;i < m;i++)
         matrix[i] = new int[n];

     cout << endl << "input matrix:" << endl;

     for(int i = 0; i < m; i++)
         for(int j = 0; j < n; j++)
             cin >> matrix[i][j];

     lines = m;
     columns = n;
 }
 void print_matrix(int **&matrix, int &lines, int &columns)
 {
     for(int i = 0; i < lines; i++)
     {
         for(int j = 0; j < columns; j++)
             cout << matrix[i][j] << " ";
         cout << endl;
     }
 }


 int find_max(int **matrix, int lines, int columns, int &max_count)
 {
     int max = INT_MIN;
     max_count = 0;
     for(int i = 0; i < lines; i++)
         for(int j = 0; j < columns; j++)
         {
             if(matrix[i][j] > max)
             {
                 max = matrix[i][j];
                 max_count = 1;
             }
             else
                if(matrix[i][j] == max)
                    ++max_count;
         }
     return max;
 }


int main()
{
    int **matrix = nullptr;
    int m=0, n=0, count=0;
    input_matrix(matrix, n, m);
    cout << endl;
    print_matrix(matrix, n, m);
    cout << endl;
    int max = find_max(matrix, n, m, count);
    cout << "max=" << max << " count=" << count << endl;
    for(int i = 0; i < n; i++)
        delete[]matrix[i];
    delete []matrix;
}

По просьбе господина Макс Лангхоф Я также хотел бы предложить более современное решение, основанное на Контейнер std :: vector , который не требует указателей и ручного управления памятью.Это простая матрица классов:

#include <algorithm>
#include <iostream>
#include <vector>
#include <cstdint>

using namespace std;

 class matrix
 {
 private:
     vector<vector<int>>    m_data;
 public:
     matrix(int cols, int rows)
     {
         m_data.resize(cols);
         for(auto &r : m_data)
             r.resize(rows);
     }

     int max_element()
     {
         int max = INT_MIN;
         for(auto &row: m_data)
         {
             auto maxinrow = *std::max_element(row.begin(), row.end());
             if(maxinrow > max)
                 max = maxinrow;
         }
         return max;
     }
     int element_count(int elem)
     {
         int count = 0;
         for(auto &row : m_data)
             count += std::count_if(row.begin(), row.end(), [elem](int a){return a == elem;});
         return count;
     }

     friend istream& operator>>(istream &os, matrix &matr);
     friend ostream& operator<<(ostream &os, matrix &matr);
 };

Операторы ввода и вывода могут быть реализованы следующим образом:

 istream& operator>>(istream &os, matrix &matr)
 {
     for(int i = 0; i < matr.m_data.size(); i++)
     {
         for(int j = 0; j < matr.m_data[i].size(); j++)
             cin >> matr.m_data[i][j];
         cout << endl;
     }
     return os;
 }
 ostream& operator<<(ostream &os, matrix &matr)
 {
     for(int i = 0; i < matr.m_data.size(); i++)
     {
         for(int j = 0; j < matr.m_data[i].size(); j++)
             cout << matr.m_data[i][j] << " ";
         cout << endl;
     }
     return os;
 }

И пример использования этой матрицы:

int main()
{
    int m = 5, n = 4;
    matrix matr(m, n);
    cout << "input matrix:" << endl;
    cin >> matr;
    cout << endl << matr;
    int max = matr.max_element();
    cout << "max: " << max << " count:" << matr.element_count(max) << endl;
}
0 голосов
/ 29 ноября 2018

Оформить заказ примерно так

#include <iostream>
#include <set>
#include <vector>

int main() {
int rowsNo, columnsNo;
std::cin >> rowsNo >> columnsNo;
std::vector<int> matrix(rowsNo*columnsNo);

//Creating matrix
for(auto row = 0; row < rowsNo; ++row) {
    for (auto column = 0; column < columnsNo; ++column)
        std::cin >> matrix[row*columnsNo + column];
}
auto maxValue = -51;
//Finding positions of maximums
std::set<int> linesWithMaxValue;
for (auto position = 0; position < matrix.size(); ++position) {
    if(matrix[position] == maxValue) 
        linesWithMaxValue.insert(position / columnsNo);
    else if(matrix[position] > maxValue) {
        linesWithMaxValue.clear();
        maxValue = matrix[position];
        linesWithMaxValue.insert(position / columnsNo);
    }
}

//Print info
const auto numberOfMaxValues = linesWithMaxValue.size();
std::cout << "Number of maxiums: " << numberOfMaxValues << std::endl;
std::cout << "Lines that contains maximum:";
for (const auto& lineId : linesWithMaxValue)
    std::cout << " " << lineId;

    return 0;
}
0 голосов
/ 29 ноября 2018

int vekt[m]; - это не стандартный C ++, это массив переменной длины (который некоторые компиляторы допускают как расширение).Вместо этого используйте std::vector.

Это также исправит ошибку , которая у вас есть в настоящее время: Если cnt >= n (т.е. если вы найдете больше максимумов, чем в матрице есть линии), вы выйдете за пределы lines, и ваша программа, скорее всего, будет аварийно завершать работу (хотя может произойти все что угодно), что более вероятно случится с более крупными матрицами.

Вместо этого вы можете сделать это:

  • Объявление и инициализация:
    std::vector<int> linesWithMaxima;
  • Когда вы найдете другое значение, равное текущему максимуму:
    linesWithMaxima.push_back(i+1);
  • Когда вы найдетеновый максимум (больше, чем текущий):
    linesWithMaxima.clear();
    linesWithMaxima.push_back(i+1);

Обратите внимание, что здесь будет показана строка с несколькими (одинаковыми) максимумами несколько раз.Если вы хотите избежать дубликатов, вы можете либо проверить, что вы еще не добавили текущую строку (linesWithMaxima.back() != i+1), либо использовать std::sort, std::unique и std::vector::erase.

Кроме этого, ваш код выглядит нормально.Я бы рекомендовал лучше именовать индексы цикла (line вместо i и т. Д.) И, возможно, объединить циклы p и j, потому что разделение их, похоже, не имеет смысла.И если вы хотите самое отрицательное целое число, используйте std::numeric_limits<int>::lowest().

...