题目如下:题目描述,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
在《剑指offer》一书中,提供了两种思路,第一种使用快速排序,第二种使用数组本身的特点做,具体方法分别讨论如下:
第一种解法,使用快速排序:
我们可以使用快速排序,每次求出一个数字在排序好的序列中的位置。从题目上来看,如果一个数字出现的次数比该数组的一半还多,就是说明,该数字应该出现在排序好的序列中的中间位上,因此,我们可以使用快速排序,找到在排序好的序列中在中间位置的数字,然后判断一下这个数字出现的次数是不是我们要找的。具体代码如下:
class Solution {
public:
int Partition(vector<int> &numbers, int length, int start, int end) {
swap(numbers[start], numbers[end]);
int small = start - 1;
for (int i = start; i < end; i++) {
if (numbers[i] < numbers[end]) {
small++;
if (i != small) {
swap(numbers[small], numbers[i]);
}
}
}
small++;
swap(numbers[small], numbers[end]);
return small;
}
int getResult(vector<int> &number, int length, int start, int end) {
int middle = length >> 1;
int index = Partition(number, length, start, end);
while (middle != index) {
if (index < middle) {
start = index + 1;
index = Partition(number, length, start, end);
}
else {
end = index - 1;
index = Partition(number, length, start, end);
}
}
int count = 0;
for (auto x : number) {
count += (x == number[index]);
}
if (count * 2 > length) return number[index];
else return 0;
}
int MoreThanHalfNum_Solution(vector<int> numbers) {
if (numbers.size() == 0) return 0;
else return getResult(numbers, numbers.size(), 0, numbers.size() - 1);
}
};
第二种解法:使用数组本身的特点,如果该数字出现的次数超过整体数组的长度,那么所有数字加起来,都没有那个数字出现的次数多。可以刚开始设置一个次数count,和一个初始化下标index。从前到后遍历这个数组,如果该数组的某一位和前一个为相同,则count加一,否则减一,某次循环中如果count为0,则将该位置的下标赋值给index,次数加一。
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int index = 0;
int count = 0;
for (int i = 0; i < numbers.size(); i++) {
if (numbers[i] == numbers[index]) {
count++;
}
else if (count == 0) {
index = i;
}
else {
count--;
}
}
count = 0;
for (int i = 0; i < numbers.size(); i++)
count += (numbers[index] == numbers[i]);
if (count <= numbers.size() >> 1) return 0;
return numbers[index];
}
};