大小为N的数组A,其主要元素就是一个出现次数超过N/2的元素(从而这样的元素只有一个或者不存在) . 例如, 数组
3, 3, 4, 2, 4, 4, 2, 4, 4
有一个主要元素4, 而数组
3, 3, 4, 2, 4, 4, 2, 4
没有主要元素. 如果没有主要元素, 那么你的程序应该指出来. 下面是求解该问题的一个算法的框架:
首先找出主要元素的一个候选元(这是难点)。这个候选元是唯一有可能是主要元素的元素。第二步确定是否这个候选元是主要元素。为了找出候选元,构造第二个数组B。比较A1和A2,如果它们相等则取其中之一加到数组B中;否则什么都不做;然后比较A3和A4,按同样的方式处理,其次类推直到读完这个数组,然后递归的寻找数组B中的候选元,它也是A的候选元. (为什么?)
a, 递归如何终止?
b, 当N是奇数时, 如何处理?
c, 该算法的运行时间是多少?
d, 我们如何避免使用附加数组B?
e, 编写一个程序求解主要元素.
自己写的考虑不全面,还是参考网上有严谨证明思路,效率最高的实现吧。
解答:
a, 当数组B的元素个数等于0或者1时, 递归终止
b, 如果前N-1个元素有主元, 那么最后一个元素不管是不是主元都对结果没有影响;
如果前N-1个元素没有主元, 那么加上最后一个元素之后, 就有可能使整个数组存在主元, 所以最后一个元素有可能是主元
所以最后的算法应该是这样的:
如果数组元素的个数是偶数, 就找出候选元, 然后再遍历整个数组, 确定这个候选元是否是主元
如果数组元素的个数是奇数, 那么就先从前N-1个元素中找出候选元,
遍历整个数组, 如果这个候选元就是主元, 那么就结束了,
遍历整个数组, 如果这个候选元不是主元, 那么就把最后一个元素当做候选元, 再遍历数组, 确定这个候选元是否就是主元
c, 对于偶数, T(n) = T(n/2) + n
根据Master定理: a = 1, b = 2, logba = 0, f(n) = O(1), f(n) > n logba 所以T(n) = O(n).
对于奇数, 只多了一次遍历, 所以T(n) = O(n) + O(n) = O(n)
d, 仍然是数组中的每两个元素相比较, 先比较A1和A2, 如果相等就和数组最前面的元素交换, 如果不相等就不交换, 再比较A3和A4, 如果相等就和前一个比较之后交换过的元素的下一个位置的元素交换, 如果不相等就不交换, 按同样的方式处理,其次类推直到读完这个数组,然后递归的寻找数组B中的候选元,它也是A的候选元.
e, 代码:
#include <iostream>
#include <vector>
using namespace std;
#define NotAMainCell -100
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
bool IsMainCell(vector<int> &arr, int ProbablyMaincell)
{
int count = 0;
for (int i = 0; i < arr.size(); i++)
if (arr[i] == ProbablyMaincell)
count++;
if (count > arr.size() / 2)
return true;
else
return false;
}
int FindMainCell(vector<int> &arr, int p)
{
if (p == 0)
return NotAMainCell;
if (p == 1)
{
if (IsMainCell(arr, arr[0]) == true)
return arr[0];
else
return NotAMainCell;
}
for (int i = 0, len = 0; i < p; i = i + 2)
{
if (arr[i] == arr[i + 1])
swap(arr[i], arr[len++]);
if (i == p - 2)
{
return FindMainCell(arr, len);
}
else if (i == p - 3)
{
int result = FindMainCell(arr, len);
if (result == -100)
{
if (IsMainCell(arr, arr[arr.size() - 1]) == true)
return arr[arr.size() - 1];
else
return NotAMainCell;
}
else
return result;
}
}
}
int main()
{
int n;
vector<int> arr = {3,3,4,2,4,4,2,4,4};
vector<int> arr1 = { 3,3,4,2,4,4,2,4 };
int result = FindMainCell(arr, arr.size());
if (result == NotAMainCell)
cout << "没有主元" << endl;
else
cout << "主元是" << result << endl;
return 0;
}
参考:http://www.cnblogs.com/XiangfeiAi/p/4758939.html