資料結構經典面試題:在字串中找到出現頻率大於50%的那個字元
阿新 • • 發佈:2018-12-31
來源:我是碼農,轉載請保留出處和連結!
本文連結:http://www.54manong.com/?id=13
問題描述:
在某個字串中(字串可能很長,比如有幾千萬個字元),請找出某個出現頻率大於50%的那個字元。例如:在字串"aabcdaa"中,字串長為7,字元'a'出現了4次,其出現頻率大於50%,因此'a'就是最終要輸出的字元。
問題分析:
思路1:
解決這個問題最簡單的方法就是遍歷一遍字串,針對每個字元都統計出其出現的次數,最後再遍歷一遍這些次數,看哪個字元的次數超過了總次數的50%。該方法的優點是思路簡單明瞭,缺點是額外的儲存空間耗費大,演算法時間複雜度高。
思路2:
思路3:能否不排序呢?當然可以!我們對整個字串遍歷一遍,遍歷的過程中,每當遇到兩個不同的字元時,就把它們兩個都刪除掉,這樣,最終當字串中沒有不同字元(即只有種字元)時,剩下的這種字元一定就是我們所要求的出現頻率超過50%的那個字元了。比如在字串"aabcdaa"中,我們將"ab","cd"分別刪除,最終字串中剩下的都是字元"a"了,"a"即為所求。
程式碼如下:
//在字串中找到出現頻率大於50%的那個字元 char get_char(char *ch) { char str; int times = 0; while(*ch) { if(times == 0) str= *ch, times = 1; else { if(str== *ch) times++; else times--; } ch++; } return str; }
某個字元str如果出現頻率大於一半,比如出現頻率為55%,那麼其他字元出現頻率的總和為(1-55%)=45%,字元str出現頻率比其他字元出現頻率的總和大(55%-45%)=10%,按照上述我們的程式思路,在最壞的情況下,每次抵消的兩個字元中都有一個str,那麼最終還能剩10%的字元str。該演算法的時間複雜度為O(n)。
問題擴充套件:
在一個int型陣列中,某三個數字出現頻率分別大於25%,請找出這三個數字。
思路:
和原問題大同小異,只要降低規模即可,每次抵消四個不相同的數字,不斷重複,最後剩下的三個數字就是答案。
程式碼如下:
int candiA = 0, candiB = 0, candiC = 0;
void get_three_num(int num[])
{
int countA = 0, countB = 0, countC = 0;
for (int i = 0; i < num.Length; i++)
{
if (countA == 0 || countB == 0 || countC == 0 )
{
if (countA == 0)
{
if (countB != 0 && num[i] == candiB)
countB++;
else if (countC != 0 && num[i] == candiC)
countC++;
else
{
candiA = num[i];
countA++;
}
}
else if (countB == 0)
{
if (countA != 0 && num[i] == candiA)
countA++;
else if (countC != 0 && num[i] == candiC)
countC++;
else
{
candiB = num[i];
countB++;
}
}
else if (countC == 0)
{
if (countA != 0 && num[i] == candiA)
countA++;
else if (countB != 0 && num[i] == candiB)
countB++;
else
{
candiC = num[i];
countC++;
}
}
}
else
{
if (num[i] == candiA)
countA++;
else if (num[i] == candiB)
countB++;
else if (num[i] == candiC)
countC++;
else
{
countA--;
countB--;
countC--;
}
}
}
}