數組中出現次數超過一半的數字
方法1.
(1)快排中的 partition()的功能是找到 pivot ,並且將pivot放在排好序的最終位置。(2)所以,如果有次數超過一半的數字,那麼對數組排序後,中間的元素一定是那個元素。
所以使用partition()的返回值進行判斷,
如果 pivot < middle, 快排pivot之後的元素,
pivot > middle, 快排pivot之前的元素。
直到 pivot == middle。
然後再判斷該元素出現的次數是否超過一半。
!!問題:
(1) 會改變原數組的值,因爲partition()會交換
方法2. 只遍歷, 不交換
遍歷數組,保持2個變量。數字a, 次數b。如果某個數出現超過一半,那麼也就是說,其他說出現次數之和不超過一半。
初始
a = array[0];
b = 1;
遍歷數組,
(1)如果 a[i] == a,++b
else --b;
(2)如果 0 == b, a[i], b= 1;
之後還得需要檢查一下base次數是否大於一半
a ---- 要統計的數。
b ---- 其他數出現的次數。
代碼
int qPartition(int *a, int low, int high)
{
int pivot = a[low];
while(low < high)
{
while(low < high && a[high] >= pivot) --high;
a[low] = a[high];
while(low < high && a[low] <= pivot) ++low;
a[high] = a[low];
}
a[low] = pivot;
return low;
}
bool isMoreThanHalf(int *a, int length, int result)
{
int cnt = 0;
int i;
for(i = 0; i < length; ++i)
{
if(result == a[i])
++cnt;
}
return cnt * 2 > length;
}
bool isArrayVaild(int *a, int length)
{
if(NULL == a || length <= 0)
return false;
return true;
}
int RESULT_FLAG = 0;
/// 方法1.
int MoreThanHalf(int *a, int length)
{
if(NULL == a || length <= 0)
return 0;
int middle = length >> 1;
int part = qPartition(a, 0, length - 1);
while(part != middle)
{
if(part < middle)
{
part = qPartition(a, part + 1, length - 1);
}
else
{
part = qPartition(a, 0, part - 1);
}
}
if(isMoreThanHalf(a, length, a[middle]))
return a[middle];
else
return 0;
}
/// 方法2.
int MoreThanHalf_1(int *a, int length)
{
if(!isArrayVaild(a, length))
{
RESULT_FLAG = -2;
return -1;
}
int base, num, i;
base = a[0];
num = 1;
for(i = 1; i < length; ++i)
{
if(0 == num)
{
base = a[i];
num = 1;
}
else if(base == a[i])
++num;
else
--num;
}
if(isMoreThanHalf(a, length, base))
RESULT_FLAG = 0;
else
RESULT_FLAG = -1;
return base;
}
測試
void test()
{
///int a[] = {1,2,3,2,2,2,5,4,2};
int a[] = {2,3,1,1,1};
int length = sizeof(a) / sizeof(*a);
///cout<<MoreThanHalf(a, length)<<endl;
int result = MoreThanHalf_1(a, length);
if(!RESULT_FLAG)
cout<<result<<endl;
else
cout<<"not have one :: "<<result<<endl;
}