如题,若存在超过一半长度的数字,返回它,反之则返回0(这种返回并不好,但是为了简化问题和说明思想)
方法一
思路:
1)从头开始遍历数组,用一个标记位times=1开始,用一个变量来记录候选的值result,初始化为数组第一个数字;当遍历时遇见相同的则times加1,不同的就减1,若times==1,则更新result 为当前遍历的值。
2)原理:试想,如果刚好有一个数等于长度的一半,那么times加和减的次数相等,最后为0;当大于长度的一半,则加的次数大于减的次数,这个输就是最后一次把times设为1对应的记录数;若出现次数最多的一个数小于长度一半,则减的数目大于加的数目。
3)下图中用Array表示数组,times为标记数,当前候选值result。第一次让times变为1的记录就是要找的。
下标 i | 0 | 1 | 2 | 3 | 4 | 5 |
times | 1 | 0 | 1 | 0 | 1 | 0 |
Array[i] | 1 | 2 | 3 | 4 | 5 | 1 |
result | 1 | 1 | 2 | 2 | 4 | 4 |
下标 i | 0 | 1 | 2 | 3 | 4 | 5 |
times | 1 | 0 | 1 | 2 | 1 | 2 |
Array[i] | 1 | 2 | 1 | 1 | 5 | 1 |
result | 1 | 1 | 1 | 1 | 1 | 1 |
实现代码:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int len = numbers.size();
if(len<1) return 0;
//-------------------------------------
int result = numbers[0];
int times = 1;
for(int i = 1; i<len;++i)
{
if(0==times)
{
result = numbers[i];
times = 1;
}
else if(numbers[i] == result)
++times;
else
--times;
}
//-------------------------------------
//-----判断是否有数字超过数组长度的一半------
int numtimes = 0;
for(int i=0;i<len;++i)
{if(numbers[i]==result)
numtimes++;
}
if(numtimes*2<=len)
return 0;
//-------------------------------------
return result;
}
-------------------------------------------------------------------
方法二
当然还有很多方法,再介绍一种实用的方法,既然某数字出现的次数超过了数组长度的一半,那么考虑将数组进行排序,则中间位置的数就是我们要找的。
1)排序,可以自己写,也可以利用标准库中的sort()函数,在#include<algorithm.h>中。
2)取中间位置的数字,就是所求。
3)问题是如何判断是否存在这样的一个数字。那么可以在中间位置的数向两边扩展,求连续相等的数子的长度,判断该长度是否大于总长度的一半。
具体代码就不写了,思路已经清晰,如果要求不能用标准库函数,则难点在于写排序算法。参考我总结的排序算法:
-----------------------------------------------------------------