要求
- 时间限制:1秒
- 空间限制:32768K
- 热度指数:275777
- 本题知识点: 数组
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路
思路一:守阵地
采用攻守阵地的思想(来源于牛客网评论)。时间复杂度和空间复杂度都为
O
(
n
)
O(n)
O(n)。
首先设置第一个数字为士兵守阵地,count=1;往后遍历数组,如果遇到的值不等于当前的士兵,并且count不为0的情况下,count减一,即失去了一个阵地;而如果count为0(没有阵地可以失去了),则将当前值设置为士兵守阵地,并且将count置1;继续向后遍历直至遍历完。则最后剩下的士兵即有可能为要找的值。最后再遍历一遍数组即可确认。
这里可以确定的是如果有满足条件的值,那么一定会幸存下来,而如果没有满足条件的值,无法确定最后得到什么值。因此必须再遍历一次确认结果。即是通过两两抵消,如果样例给的数组确实有个数的次数超过一半,抵消到最后一定就是要求的那个数了。
python实现
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
if not numbers:
return 0
count = 1
tmp = numbers[0]
for i in range(len(numbers)-1):
if numbers[i+1]==numbers[i]:
count += 1
elif count != 0:
count -= 1
elif count == 0:
tmp = numbers[i+1]
count = 1
count = 0
for i in range(len(numbers)):
if numbers[i] == tmp:
count += 1
return tmp if 2*count>len(numbers) else 0
- 运行时间:25ms
- 占用内存:5624k
C++实现
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int length = numbers.size();
int count = 1; int tmp = numbers[0];
for (int i=0; i<length-1; i++){
// 如果后一个值和当前值相等则表明守住了阵地count加一
if (numbers[i+1] == numbers[i])
count++;
// 不想等没守住阵地;
// 若count不为0继续减1
else if (count != 0)
count--;
// 若count为0重置主人
else if (count == 0){
tmp = numbers[i+1];
count = 1;
}
}
// 判断tmp是否满足条件
count = 0;
for (int i=0; i<length; i++)
if (numbers[i]==tmp)
count++;
if (count*2 <= length)
tmp = 0;
return tmp;
}
};
- 运行时间:3ms
- 占用内存:476k
思路二:快排
该思路分为两步,即先用快排排序;排序后可知如果存在满足条件的值必在中间位置,然后即可再遍历一次数组统计候选值出现的次数做出最后判断。此种方法的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)。主要是为了练习快排的思路。
python实现
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
if not numbers:
return 0
length = len(numbers)
def quickSort(numbers, left, right):
if left >= right:
return
i, j, tmp = left, right, numbers[i]
while i < j:
while i<j and numbers[j]>=tmp:
j -= 1
if (i < j):
numbers[i] = numbers[j]
while i < j and numbers[i]<=tmp:
i += 1
if i < j:
numbers[j] = numbers[i]
numbers[i] = tmp
quickSort(numbers, left, i-1)
quickSort(numbers, i+1, right)
candidate = numbers[length//2]
count = 0
for i in range(length):
if candidate == numbers[i]:
count += 1
return candidate if count*2>length else 0
- 运行时间:30ms
- 占用内存:5856k
C++实现
class Solution {
public:
void quickSort(vector<int> &numbers, int left, int right) {
if (left >= right)
return;
int i = left; int j = right;
int tmp = numbers[i];
while (i < j){
while (i<j && numbers[j]>=tmp) j--;
if (i<j) numbers[i] = numbers[j];
while (i<j && numbers[i]<=tmp) i++;
if (i<j) numbers[j] = numbers[i];
}
numbers[i] = tmp;
quickSort(numbers, left, i-1);
quickSort(numbers, i+1, right);
}
int MoreThanHalfNum_Solution(vector<int> numbers) {
int length = numbers.size();
if (length==0) return 0;
quickSort(numbers, 0, length-1);
// 如果存在满足条件的值一定是中间这个值
int candidate = numbers[length/2];
int count = 0;
for (int i=0; i<length; i++)
if (numbers[i] == candidate)
count++;
return 2*count>length?candidate:0;
}
};
- 运行时间:3ms
- 占用内存:480k