2015某移動電臺app秋季面試題
很常見的問題,解決方法有很多,能想到的是:
- 快排裏面的partition,遞歸找到中間元素,使得左邊元素小於或等於中間元素,右邊元素大於或等於中間元素。時間複雜度爲O(n),空間複雜度爲O(n),原來元素的順序被打亂了。
- hashmap,將數組元素建立hashmap,key爲數組元素的值,value爲元素出現頻次,找到頻次出現超過半數的key,複雜度和上述一樣
上面兩種方法計算複雜度爲O(n),但空間複雜度爲O(n),不是最優解,下面的方法空間複雜度爲O(1):
用兩個臨時變量,一個保存數組元素,一個記錄出現頻次。
遍歷數組,如果當前元素和臨時元素相等,頻次加一;
否則減一,如果頻次小於1,則臨時元素變爲當前元素,出現頻次變爲1。
分析:如果一個數出現頻次大於半數,那麼它出現的頻次必然大於其他所有元素出現的頻次,一次遍歷後,臨時元素保存的肯定是頻次超過一半的元素。
代碼如下:
//
// main.cpp
// moreThanHalf
//
// Created by LiLingyu on 15/10/20.
// Copyright © 2015年 LiLingyu. All rights reserved.
//
#include <iostream>
/*
已知有數組裏面有個元素出現次數超過一半,問如何找出這個數,時間複雜度O(n),空間複雜度O(1)
常見的hashmap時間複雜度爲O(n),空間複雜度爲O(n),不是最優選
*/
bool isMoreThanHalf(int* a, int len, int number)
{
int counter = 0;
for (int i=0; i<len; i++) {
if (a[i]==number) {
counter++;
if (counter*2>len) {
return true;
}
}
}
return false;
}
int moreThanHalf(int* a, int len)
{
int counter = 1;
int tmp = a[0];
for (int i=1; i<len; i++) {
if(a[i]==tmp)
{
counter++;
}
else
{
counter--;
if (counter<=0) {
tmp=a[i];
counter=1;
}
}
}
/*
if (counter>=0) {
return tmp;
}
else{
return -1;
}*/
if (isMoreThanHalf(a, len, tmp)) {
return tmp;
}
else
{
printf("error: no number appears more than half times!\n");
return -1;
}
}
int main(int argc, const char * argv[]) {
const int len=10;
int a[len] = {1, 1, 5, 5, 1, 5, 1, 5, 5, 5};
for (int i=0; i<len; i++) {
printf("%d\t", a[i]);
}
printf("\n");
printf("result: \n");
printf("%d\n", moreThanHalf(a, len));
return 0;
}