题目
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路
- 数组元素可以被改变
时间复杂度 O ( n ),快排时间复杂度是O(NlogN)是因为其对 middle左边和右边是有序的,而本题只要找到middle即可,两边不一定是有序的。
这个数字是统计学上的中位数,即长度为n的数组中第n/2大的数字。我们有成熟的O(n)算法得到数组中任意第k大的数字。
这种算法是受快速排序算法的启发,在随机快排中,先随机选择一个数字,然后将比它小的数字都放在它的左边,比它大的都放在它的右边。
如果调整好位置后,这个选中的数字的下标刚好是n/2,那么这个数字就是数组中的中位数。
如果它的下标大于n/2,那么中位数应该在它的左边,可以接着在它的左边查找;下标小于n/2的情况类似.
- 数组元素保持不变
时间复杂度 O ( n )
数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其他所有数字出现次数的和还要多。
因此我们可以考虑在遍历数组的时候保存两个值:一个是数组的一个数字,一个是次数。当我们遍历到下一个数字的时候。
如果下一个数字和我们之前保存的数字相同,则次数加1;
如果下一个数字和我们之前保存的数字不同,则次数减1;
如果次数为零,我们需要保存下一个数字,并把次数设为1。
由于我们要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字肯定是最后一次把次数设为1时对应的数字。
不存在的判断条件? :再遍历一次~统计次数与len的一半比较
方法三:hash法
首先创建一个hash_map,其中key为数组元素值,value为此数出现的次数。遍历一遍数组,用hash_map统计每个数出现的次数,并用两个值存储目前出现次数最多的数和对应出现的次数,此时的时间复杂度为 O(n),空间复杂度为O(n)
#include <iostream>
#include <vector>
using namespace std;
class Solution
{
public:
int moreThanHalfNumber(vector<int> &array)
{
int len = array.size();
if (len == 0)
return -1;
int middle = len / 2;
int start = 0;
int end = len - 1;
int index = partion(array, start, end);
while (index != middle)
{
if (index > middle)
index = partion(array, start, index - 1);
else
index = partion(array, index + 1, end);
}
//判断是否有超过一半的元素是相同的
int count = 0;
for (int i = 0; i < len; i++)
{
if (array[i] == array[middle])
count++;
}
return count > len / 2 ? array[middle] : 0;
}
private:
int partion(vector<int> &array, int left, int right)
{
int baseNum = array[left];
while (left < right)
{
while (left < right && array[right] >= baseNum)
right--;
array[left] = array[right];
while (left < right && array[left] <= baseNum)
left++;
array[right] = array[left];
}
array[left] = baseNum;
return left;
}
};
int main()
{
Solution s;
vector<int> array{2, 3, 2, 1, 4, 5, 2,2, 2, 2};
cout << s.moreThanHalfNumber(array) << endl;
system("pause");
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
class Solution
{
public:
int moreThanHalfNumber(vector<int> numbers)
{
int len = numbers.size();
if (len == 0)
return 0;
int result = 0, count = 1;
int i;
for (i = 1; i < len; i++)
{
if (result == numbers[i])
count++;
else
count--;
if (count == 0)
{
result = numbers[i];
count = 1;
}
}
//判断是否有超过一半次数的元素
count = 0;
for (i = 0; i < len; i++)
{
if (result == numbers[i])
count++;
}
return (count > len / 2) ? result : 0;
}
};
int main()
{
Solution s;
vector<int> number{ 2, 2, 1, 2, 3, 2, 2, 2, 2, 4, 5, 2, 1, 6, 7, 2, 2 };
cout << s.moreThanHalfNumber(number) << endl;
system("pause");
return 0;
}