Я проверил SO и увидел две проблемы, связанные с одной и той же постановкой проблемы. Однако ни один из них не содержал того, что я ищу. Задача состоит в том, чтобы вывести 1, если массив из n элементов содержит элемент, который встречается более n/2 раз, используя стратегию разделяй и властвуй.
Я разработал то, что я считаю рабочим решением, основанным на том факте, что базовый вариант представляет собой подмассив с одним элементом, который (очевидно) является основным элементом в подмассиве. Затем я перехожу к сравнению этих элементов большинства в подмассивах, задаюсь вопросом, встречаются ли они в конечном счете более чем n/2 раз.
Для получения дополнительной информации см. https://classes.soe.ucsc.edu/cmps102/Fall01/solutions4.pdf (задача 4)
Я написал два разных решения этой проблемы, одно с использованием очень наивного алгоритма O (n ^ 2), чтобы проверить, правильно ли мое решение для всех случаев, и одно, пытающееся реализовать алгоритм, описанный в ссылке выше.
Внутри main я проверяю свое решение на соответствие очевидно правильному, но наивному. Однако при запуске я получаю ошибку SIGABRT (сигнал 6). Мой отладчик говорит мне проверить наличие malloc, объект, вероятно, был изменен после освобождения.
Теперь я не могу сказать, верно ли мое решение. Я действительно не знаю, что происходит с плохим распределением, я относительно новичок в C++.
Код идет ниже:
#include <algorithm>
#include <iostream>
#include <vector>
using std::vector;
int get_majority_element(vector<int> &a, int left, int right) {
int m;
int majority_left, majority_right; // majority element in either sub array
int count_right = 0, count_left = 0; // count for above
int leftt, rightt; // endpoints
if (a.size() == 1) {
return a[0];
}
else {
m = (left + right)/2; // calculate mid point
vector<int> b_left(m);
vector<int> b_right(right - m);
// get left sub array
for (int i = 0; i < m; i++) {
b_left[i] = a[i];
}
// set new endpoints
leftt = 0;
rightt = m;
majority_left = get_majority_element(b_left, leftt, rightt);
for (int i = 0; i < right - m + 1; i++) {
b_right[i] = a[m+i];
}
leftt = m;
rightt = right - m + 1;
majority_right = get_majority_element(b_right, leftt, rightt);
// if there is a majority element, count its frequency
if (majority_left != -1) {
for (int i = 0; i < a.size(); i++) {
if (a[i] == majority_left)
count_left++;
}
}
if (majority_right != -1) {
for (int i = 0; i < a.size(); i++) {
if (a[i] == majority_right)
count_right++;
}
}
// if both elements in sub arrays are majority and they're different, there is no majority element
if (count_left == count_right && majority_left != majority_right) {
return -1;
}
// check if either sub array has a majority element that occurs more than n/2 times
else if (count_right > count_left && count_right > a.size()/2) {
return majority_right;
}
else if (count_left > count_right && count_left > a.size()/2){
return majority_left;
}
}
return -1;
}
int get_majority_fast(vector<int> &a, int left, int right){
std::reverse(a.begin(),a.end());
int current = 0;
int count;
for (int i = 0; i < a.size(); i++) {
current = a[i];
count = 0;
for (int j = 0; j < a.size(); j++) {
if (a[j] == current)
count ++;
}
if (count > a.size()/2)
return 1;
}
return -1;
}
int main() {
// std::cin >> n;
// vector<int> a(n);
// for (size_t i = 0; i < a.size(); ++i) {
// std::cin >> a[i];
// }
// std::cout << (get_majority_fast(a, 0, a.size()) != -1) << '\n';
while(true){
int one, two;
int n = rand() % 100 ;
std::cout << n << "\n";
vector<int> a;
for (int i = 0; i < n; ++i) {
a.push_back(rand() % 100);
}
one = get_majority_element(a, 0, a.size());
two = get_majority_fast(a, 0, a.size() != -1);
if (one != two) {
std::cout << "Wrong answer: " << one << ' ' << two << "\n";
break;
}
else {
std::cout << "OK\n";
}
}
}
get_majority_fast()
не использует аргументыleft
илиright
? И почему вы передаете логическое значение в качестве аргументаright
? - person Barmar   schedule 31.01.2017std::vector
является использование функцииat()
. Он выдаст исключение, если вы когда-нибудь выйдете за пределы вектора. Вы делаете это прямо здесь:b_right[i] = a[m + i];
-- измените это наb_right[i] = a.at(m + i)
, и вы должны получить исключениеstd::out_of_range
как показано в этом примере - person PaulMcKenzie   schedule 31.01.2017get_majority_fast
довольно быстро, поэтому просто скопировал определение функции из предыдущего. Однако передаваемые ему аргументы не имеют значения. Я проверю, не выходит ли за пределы, спасибо. - person Emilio Botero   schedule 31.01.2017a[m+i]
) - person Emilio Botero   schedule 31.01.2017[ ]
для доступа к элементу вектора, это неопределенное поведение для доступа к элементу за пределами границ. Нет никакой гарантии, что программа рухнет, даже если она неправильная. Используяat()
гарантии, программа останавливается при доступе за границу. Я не использовал тестовые данные - я просто использовал программу, которую вы опубликовали, и запустил ее с небольшим изменением, используяat()
. Короче говоря, ваша программа всегда ошибалась, но вы никогда не знали об этом и были одурачены, увидев появляющийся вывод. - person PaulMcKenzie   schedule 31.01.2017a.at()
. Однако из Python я привык использовать[ ]
. Спасибо! - person Emilio Botero   schedule 31.01.2017