题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字
思路:剑指中提供的思路是数组中有一个数字出现的次数超过数组长度的一半,也就是说它的出现次数比其他所有数字出现的次数的和还要多。因此我们可以考虑在遍历数组的时候保存两个值:一个是数组中的第一个数字;另一个是次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数就加1;如果下一个数字和我们之前保存的数字不同就减1.如果次数为0,那我们需要保存下一个数字,并把次数设置为1.由于我们要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字肯定是最后一次把次数设为1时的对应的数字。
这种思路的时间复杂度是o(n).表示数量增大几倍,耗时就增大几倍。这个题目中就是遍历数组。
复杂度的一个小总结:(原文链接:https://blog.csdn.net/lkp1603645756/article/details/85013126)
(1)O(1)是最低的时空复杂度了,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变。
(2)O(n)表示数量增大几倍,耗时就增大几倍。(这个应该是线性增加)
(3)O(n^2):比如时间复杂度O(n^2),就代表数据量增大n倍时,耗时增大n的平方倍,这是比线性更高的时间复杂度。比如冒泡排序,就是典型的O(n^2)的算法,对n个数排序,需要扫描n×n次。
(4)O(log n):再比如O(log n),当数据增大n倍时,耗时增大log n倍(这里的log是以2为底的,比如,当数据增大256倍时,耗时只增大8倍,是比线性还要低的时间复杂度)。二分查找就是O(log n)的算法,每找一次排除一半的可能,256个数据中查找只要找8次就可以找到目标。
代码:
public int MoreThanHalfNum_Solution(int [] array) {
int maxCount = array[0];
int number = array[0]; //记录出现的数字
int count = 1; //记录次数
for (int i = 1; i < array.length; i++) {
if (number != array[i]) {
if (count == 0) {
number = array[i];
count = 1;
}else {
count--;
}
}else {
count++;
}
if (count == 1) {
maxCount = number; //记录下次数设为1时对应的数字
}
}
// 验证
int num = 0;
for (int j = 0; j < array.length; j++) {
if (array[j] == maxCount) {
num++;
}
}
if (num * 2 > array.length) {
return maxCount;
}
return 0;
}