我检查了SO,看到了两个处理相同问题陈述的问题。但是,它们都没有包含我正在寻找的东西。如果具有 n 元素的数组包含一个超过 n / 2 次的元素,使用分而治之策略。
我基于以下事实开发了我认为是一种有效的解决方案:基本情况是一个子数组,其中一个元素(显然)是子数组中的主要元素。然后我继续比较子阵列中的这些多数元素,询问它们最终是否超过 n / 2 次。
有关详细信息,请参阅https://classes.soe.ucsc.edu/cmps102/Fall01/solutions4.pdf(问题4)
我为这个问题编写了两个不同的解决方案,一个使用非常天真的O(n ^ 2)算法来检查我的解决方案是否适用于所有情况,还有一个尝试实现上面链接中描述的算法。
在主要内部,我强调测试我的解决方案与明显正确但天真的解决方案。但是,运行此操作后,我收到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";
}
}
}
答案 0 :(得分:0)
其中一个循环中实际上存在越界错误。修正循环如下:
for (int i = m; i < right - m ; i++) {
b_right.at(m-i) = a.at(m + i);
}
我认为奇怪的SIGABRT错误是由于一些神秘的东西。猜猜我学会了使用x.at()
另外,我还有其他一些错误。完整更正的代码如下:
#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 = -1, majority_right = -1; // majority element in either sub array
int count_right = 0, count_left = 0; // count for above
int new_left, new_right; // endpoints
if (a.size() == 1) {
return a[0];
}
else {
m = (a.size())/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.at(i) = a.at(i);
}
for (int i = 0; i < a.size() - m ; i++) {
b_right.at(i) = a.at(i + m);
}
// set new endpoints
new_left = 0;
new_right = m;
majority_left = get_majority_element(b_left, new_left, new_right);
new_left = m;
new_right = right - m;
majority_right = get_majority_element(b_right, new_left, new_right);
// 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 0;
}
else if (count_left == count_right)
return majority_left;
// 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;
}
// majority element in sub arrays isn't majority in array
else
return 0;
}
}
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() {
int n;
std::cin >> n;
vector<int> a(n);
for (size_t i = 0; i < a.size(); ++i) {
std::cin >> a[i];
}
int result;
int out;
result = get_majority_element(a, 0, a.size());
if (result != 0)
out = 1;
else
out = 0;
std::cout << out << '\n';
}
我确信我可以让它变得更漂亮但是现在我不想听到这个问题。