面試題三:數(shù)組中重復(fù)的數(shù)字

寫(xiě)在前面

c++的確是需要一直學(xué)習(xí)一直積累的編程語(yǔ)言描馅!

1而线、數(shù)組初始化列表中的元素個(gè)數(shù)小于指定的數(shù)組長(zhǎng)度時(shí),不足的元素補(bǔ)以默認(rèn)值膀篮。
int a[5] = { 0 };    // 全部初始化為0,等價(jià)于 int a[5] = {0,0,0,0,0}
int a[5] = {1};  //第一個(gè)元素被賦值為1,其他元素被賦值為0磅网,等價(jià)于int a[5] = {1,0,0,0,0}
string a[5] = {"have","fun"};  //第一個(gè)元素被賦值為“have”筷屡,第二個(gè)元素被賦值為“fun”,其他元素被賦值為“”毙死,等價(jià)于 string a[5] = {"have","fun","","",""}
2、不能對(duì)數(shù)組賦值确封,只能對(duì)數(shù)組元素初始化或賦值再菊。
int a[3];
a = {10,16,8};  //將會(huì)報(bào)錯(cuò):   error: assigning to an array from an initializer list
3、當(dāng)數(shù)組作為函數(shù)的形參進(jìn)行傳遞時(shí)腥放,數(shù)組就自動(dòng)退化為同類型的指針绿语。
4、當(dāng)字符數(shù)組表示字符時(shí)吕粹,若使用sizeof函數(shù),需要將“\0”也計(jì)算進(jìn)去聚请。

說(shuō)sizeof是函數(shù)不太準(zhǔn)確,因?yàn)閟izeof可以不加括號(hào)()驶赏。需要注意的是無(wú)論string里放多長(zhǎng)的字符串,它的sizeof()都是固定的盖文,字符串所占的空間是從堆中動(dòng)態(tài)分配的蚯姆,與sizeof()無(wú)關(guān)。也就是說(shuō)sizeof(string)和字符串的長(zhǎng)度是無(wú)關(guān)的疙驾,在一個(gè)系統(tǒng)中所有的sizeof(string)是一個(gè)固定值郭毕,這個(gè)和編譯器相關(guān)(經(jīng)測(cè)試,在codeblock中sizeof(string)的固定大小是24個(gè)字節(jié))铣卡,string字符串是存儲(chǔ)在堆上,這個(gè)屬于動(dòng)態(tài)分配的空間敞峭,對(duì)于別的整形浮點(diǎn)型數(shù)據(jù)類型則沒(méi)有這個(gè)問(wèn)題蝉仇。

題目一:

在一個(gè)長(zhǎng)度為n的數(shù)組中存放的數(shù)字都在0~n-1的范圍內(nèi)。數(shù)組中某些數(shù)字是重復(fù)的沉迹,但是不知道具體哪些數(shù)字重復(fù)了害驹,也不知道重復(fù)了幾次,請(qǐng)找出數(shù)組中任意一個(gè)重復(fù)的數(shù)字宛官。比如說(shuō)輸入長(zhǎng)度為7的數(shù)組{2,3,1,0,2,5,3},那么對(duì)應(yīng)的輸出的數(shù)字為2或者3腋么。

思路一:把數(shù)組中的所有元素從小到大排序亥揖。以此掃描排序后的數(shù)組,很容易就能找出重復(fù)的數(shù)字了。排序一個(gè)長(zhǎng)度為n的數(shù)組的時(shí)間復(fù)雜度為O(nlogn)圣贸,不需要額外的空間扳剿。
//c++實(shí)現(xiàn)
#include <iostream>
#include "stdio.h"
#include<cstring>
using namespace std;
int main()
{

    int arr[7] = {2,3,1,0,2,5,3};
    int length = sizeof(arr)/sizeof(arr[0]);
    int temp;
    //選擇排序
    for(int i = 0;i < length-1;i++){
        for(int j=i+1;j<length;j++){
            if(arr[i]>arr[j]){
                temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
    //找出所有的重復(fù)的數(shù)字并輸出
    for(int i = 0;i<length-1;i++){
        if(arr[i]==arr[i+1]){
            printf("%d ",arr[i]);
        }
    }
    return 0;
}
思路二:額外定義一個(gè)哈希表昼激,從頭到尾遍歷原數(shù)組。若元素不在哈希表中則添加并從原數(shù)組中移除瞧掺;若在哈希表中則說(shuō)明找到了重復(fù)的數(shù)字凡傅。若只需找一個(gè)重復(fù)的元素可省去在原數(shù)組中移除這一步操作,立即結(jié)束程序返回結(jié)果哼转;若需要找到所有的重復(fù)數(shù)字槽华,返回最后的原數(shù)組即可。此時(shí)遍歷數(shù)組的時(shí)間復(fù)雜度為O(n),額外申請(qǐng)的數(shù)組的空間復(fù)雜度O(n)猫态,由此可見(jiàn),這個(gè)方法是以空間換時(shí)間勇凭!

水平有限义辕,正在重拾c++,就只用Python隨便寫(xiě)了下灌砖,將就著看吧。

//python實(shí)現(xiàn)
def find(arr):
    return set([arr[x] for x in range(len(arr)-1) if arr[x]  in arr[x+1:]])
print find([2,3,1,0,5,2,3])
思路三:從頭到尾掃描數(shù)組柳譬,當(dāng)掃描到下標(biāo)為i的數(shù)字m時(shí)续镇,判斷下標(biāo)i與下標(biāo)i所對(duì)應(yīng)的數(shù)字m是否相等,若相等繼續(xù)掃描下一個(gè)元素制跟;判斷下標(biāo)為i的數(shù)字即m與下標(biāo)為m的數(shù)字即n是否相等,若相等則說(shuō)明找到了重復(fù)的數(shù)字雨膨,若不相等就把下標(biāo)為i的數(shù)字m與下標(biāo)為m的數(shù)字n交換位置聊记,繼續(xù)判斷新一輪小標(biāo)為i的數(shù)字n是否與下標(biāo)i相等撒妈。排监。舆床。如此進(jìn)行下去棋蚌,直到找到重復(fù)的數(shù)字為止。

此法我個(gè)人認(rèn)為對(duì)于這道特定的題目來(lái)說(shuō)很有效谷暮,但是并不是所有數(shù)組的元素都是小于其長(zhǎng)度的數(shù)字盛垦,若有數(shù)字大小超過(guò)其長(zhǎng)度程序就會(huì)崩潰,所以沒(méi)有很好地?cái)U(kuò)展性省撑。

#include <iostream>
#include "stdio.h"
#include<cstring>
using namespace std;
int main()
{
    int arr[7] = {2,3,1,0,2,5,3};
    int length = sizeof(arr)/sizeof(arr[0]);
    int temp;
    for(int i=0;i<length;i++){
        while(arr[i]!=i){                //如果下標(biāo)與下標(biāo)所對(duì)應(yīng)的數(shù)字不相等俯在,就一直交換比較。
            if(arr[i]!=arr[arr[i]]){     //下標(biāo)為i的數(shù)字即m與下標(biāo)為m的數(shù)字即n不相等跷乐,則把下標(biāo)為i的數(shù)字m與下標(biāo)為m的數(shù)字n交換位置
                temp = arr[arr[i]];
                arr[arr[i]]=arr[i];
                arr[i] = temp;
            }
            else{
                printf("%d ",arr[i]);
                break;
            }
        }
    }
}

題目二:

在一個(gè)長(zhǎng)度為n的數(shù)組中存放的數(shù)字都在1~n的范圍內(nèi)愕提。數(shù)組中某些數(shù)字是重復(fù)的,所以數(shù)組中至少存在一個(gè)數(shù)字是重復(fù)的浅侨,請(qǐng)找出數(shù)組中任意一個(gè)重復(fù)的數(shù)字,但不能修改輸入的數(shù)組鼓黔。比如說(shuō)輸入長(zhǎng)度為7的數(shù)組{2,3,1,0,2,5,3},那么對(duì)應(yīng)的輸出的數(shù)字為2或者3崔步。也就是說(shuō)在題目一的基礎(chǔ)上增加了一個(gè)條件:不能修改數(shù)組6泄取!列林!

思路一:由于不能修改原數(shù)組,所以很容易想到的是定義一個(gè)長(zhǎng)度為n+1的數(shù)組捏悬,從頭到尾遍歷原來(lái)數(shù)組中的數(shù)字并判斷輔助數(shù)組中下標(biāo)為m的位置上的數(shù)字是否為0润梯,若不是則把該數(shù)字m存放到這個(gè)位置上甥厦,若不是為0,則找到了重復(fù)的數(shù)字舶赔。

這個(gè)方法呢也是對(duì)這道特定的題目有效谦秧,雖說(shuō)時(shí)間復(fù)雜度為O(n),但是也有O(n)的空間復(fù)雜度。而且如果換一個(gè)存放較大數(shù)字但自身長(zhǎng)度很小的數(shù)組疚鲤,該方法就失效了。雖說(shuō)如此還是用c++實(shí)現(xiàn)一下桶略。

#include <iostream>
#include "stdio.h"
#include<cstring>
using namespace std;
int main()
{
    int arr[7] = {2,3,1,0,2,5,3};
    int length = sizeof(arr)/sizeof(arr[0]);
    int help[length+1] = {0};  //數(shù)組初始化列表中的元素個(gè)數(shù)小于指定的數(shù)組長(zhǎng)度時(shí)诲宇,不足的元素補(bǔ)以默認(rèn)值。輔助數(shù)組的類型為整型鹅心,所以自動(dòng)補(bǔ)0纺荧。
    for(int i=0;i<length;i++){
        if(help[arr[i]]==0){
            help[arr[i]] = arr[i];
        }
        else{
            printf("%d ",arr[i]);
        }
    }
}
思路二:利用二分查找的算法思想溯泣,加一個(gè)統(tǒng)計(jì)區(qū)間內(nèi)數(shù)字?jǐn)?shù)目的步驟榕茧。把1-n的數(shù)字從中間的數(shù)字m分為兩部分,前面一半為1-m肢簿,后面一半為m+1-n蜻拨。如果1-m的數(shù)字的數(shù)目超過(guò)m,那么這一半的區(qū)間里面一定包含重復(fù)的數(shù)字缎讼,否則重復(fù)的數(shù)字在另一半?yún)^(qū)間內(nèi)。繼續(xù)把重復(fù)數(shù)字所在的區(qū)間一分為二卧惜,一樣的方法判斷夹纫、分割,直到找到重復(fù)的數(shù)字茅姜。
#include <iostream>
#include "stdio.h"
#include<cstring>
using namespace std;
int countRange(int* arr,int length,int star,int middle){
    if((sizeof(arr)/sizeof(arr[0]))==0){
        return 0;
    }
    int countsOfnumbers = 0;
    for(int i=0;i<length;i++){
        if(arr[i] >= star && arr[i]<=middle){
            countsOfnumbers += 1;
        }
    return countsOfnumbers;
    }
}
int main(){
    int arr[] = {2,3,1,0,2,5,3,3};
    int length = sizeof(arr)/sizeof(arr[0]);
    int star = 1;
    int tail = length-1;
    while(tail>=star){
        int middle = ((tail-star)>>1)+star;
        int countsOfnumbers = countRange(arr,length,star,middle);
        if(tail==star){
            if(countsOfnumbers>1){
                printf("%d ",star);
            }
            else{
                break;
            }
        }
        if(countsOfnumbers>(middle-star+1)){
            tail = middle;
        }
        else{
            star = middle + 1;
        }
    }
}

這個(gè)思路存在同樣的問(wèn)題就不累贅了月匣,只適合這道題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末素标,一起剝皮案震驚了整個(gè)濱河市院刁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌任岸,老刑警劉巖狡刘,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異剑按,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)艺蝴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)猜敢,“玉大人,你說(shuō)我怎么就攤上這事鼠冕】瓒ⅲ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵憎乙,是天一觀的道長(zhǎng)趋厉。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么沈善? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任闻牡,我火速辦了婚禮,結(jié)果婚禮上罩润,老公的妹妹穿的比我還像新娘。我一直安慰自己金度,他們只是感情好严沥,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著跟伏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪受扳。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天骨宠,我揣著相機(jī)與錄音相满,去河邊找鬼。 笑死匿又,一個(gè)胖子當(dāng)著我的面吹牛建蹄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洞慎,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼劲腿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了焦人?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤忽匈,失蹤者是張志新(化名)和其女友劉穎矿辽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體雕蔽,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奕污,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年碳默,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了缘眶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片髓废。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖顶燕,靈堂內(nèi)的尸體忽然破棺而出冈爹,到底是詐尸還是另有隱情,我是刑警寧澤频伤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布憋肖,位于F島的核電站,受9級(jí)特大地震影響岸更,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜怎炊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一结胀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧糟港,春花似錦院仿、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至暮芭,卻和暖如春欲低,著一層夾襖步出監(jiān)牢的瞬間畜晰,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工腊瑟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留块蚌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓财松,卻偏偏與公主長(zhǎng)得像虎敦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子其徙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容