题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
解题思路
- 我的思路
先排序再顺序查找,时间复杂度O(nlogn) - 书上的思路
- 思路1:基于Partition函数的时间复杂度为O(n)的算法
如果把这个数组排序,那么排序后位于数组中间的数字一定就是那个出现次数超过数组长度一半的数字。也就是说,这个数字就是统计学上的中位数,即长度为n的数组中第n/2大的数字。而利用Partition函数我们可以在O(n)的时间内得到数组中任意第k大的数字。(快排牛逼)
- 思路2:根据数组特点找出时间复杂度为O(n)的算法
由于数组中有一个数字出现的次数比其他所有数字出现的次数还要多,因此我们在遍历数组的时候保存两个值:一个是数组中的一个数字,另一个是次数。当我们遍历到下一个数字的时候,如果和之前保存的数字相同,则次数加1;如果不同,次数减1。如果次数为0,那么我们需要保存下一个数字,并把次数设为1。最后我们保存的那个数字就是要找的,当然还需要验证是否满足次数超过一半,不满足则返回0。
Code
- 我的版本
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
if(!numbers.size()) return 0;
if(numbers.size() == 1) return numbers[0];
sort(numbers.begin(), numbers.end());
int cnt = 1, len = numbers.size();
for(int i = 1; i<len; i++) {
if(numbers[i] != numbers[i-1]) {
cnt = 1;
} else {
cnt++;
if(cnt > len/2) {
return numbers[i];
}
}
}
return 0;
}
};
- 思路1:基于Partition函数的时间复杂度为O(n)的算法
class Solution {
public:
int Partition(vector<int> &numbers, int st, int ed) {
srand((unsigned)time(NULL));
int pos = rand() % (ed-st+1) + st;
swap(numbers[st], numbers[pos]);
int tem = numbers[st];
while(st < ed) {
while(st < ed && tem <= numbers[ed]) ed--;
numbers[st] = numbers[ed];
while(st < ed && tem >= numbers[st]) st++;
numbers[ed] = numbers[st];
}
numbers[st] = tem;
return st;
}
bool CheckMoreThanHalfOfNum(vector<int> numbers, int result) {
int length = numbers.size(), cnt = 0;
for(int i = 0; i<length; i++) {
if(numbers[i] == result) {
cnt ++;
}
}
if(2*cnt > length) {
return true;
}
return false;
}
int MoreThanHalfNum_Solution(vector<int> numbers) {
if(!numbers.size()) return 0;
if(numbers.size() == 1) return numbers[0];
int length = numbers.size(), middle = length >> 1;
int st = 0, ed = length-1;
int partition = Partition(numbers, st, ed);
while(partition != middle) {
if(partition > middle) {
ed = partition - 1;
} else {
st = partition + 1;
}
partition = Partition(numbers, st, ed);
}
int result = numbers[middle];
if(CheckMoreThanHalfOfNum(numbers, result)) {
return result;
}
return 0;
}
};
- 思路2:根据数组特点找出时间复杂度为O(n)的算法
class Solution {
public:
bool CheckMoreThanHalfOfNum(vector<int> numbers, int result) {
int length = numbers.size(), cnt = 0;
for(int i = 0; i<length; i++) {
if(numbers[i] == result) {
cnt ++;
}
}
if(2*cnt > length) {
return true;
}
return false;
}
int MoreThanHalfNum_Solution(vector<int> numbers) {
if(!numbers.size()) return 0;
int result = numbers[0], cnt = 1;
for(int i = 1; i<numbers.size(); i++) {
if(!cnt) {
result = numbers[i];
cnt = 1;
} else if(numbers[i] == result) {
cnt++;
} else {
cnt--;
}
}
if(CheckMoreThanHalfOfNum(numbers, result)) {
return result;
}
return 0;
}
};
- java
public class Solution {
public boolean checkMoreThanHalf(int []array, int result) {
int cnt = 0, len = array.length;
for(int i = 0; i<len; i++) {
if(array[i] == result) {
cnt++;
}
}
return cnt > (len>>1);
}
public int MoreThanHalfNum_Solution(int [] array) {
if(array.length == 0) return 0;
int result = 0, cnt = 0;
for(int i = 0; i<array.length; i++) {
if(cnt == 0) {
cnt = 1;
result = array[i];
} else if(array[i] == result) {
cnt++;
} else {
cnt--;
}
}
if(checkMoreThanHalf(array, result)) {
return result;
}
return 0;
}
}
总结
产生随机数的方法
获取[st,ed]的随机整数
srand((unsigned)time(NULL));
int pos = rand() % (ed-st+1) + st;