算法的時間復雜度推導方法

算法的時間復雜度推導方法

獨立博客地址:chugang.net

語句頻度

語句頻度是指語句的重復執(zhí)行次數(shù)。

推導大O階方法

方法
  1. 用常數(shù)1取代運行時間中的所有加法常數(shù)。
  2. 在修改后的運行次數(shù)函數(shù)中唠帝,只保留最高階項澳泵。
  3. 如果最高階項存在且不是1,則去除與這個項相乘的乘數(shù)瓢谢。
常數(shù)階舉例運用

右側注釋中的 num 表示語句執(zhí)行的次數(shù)畸写。

int sum = 0, n = 100;       /* num = 1 */
sum = (n+1) * n / 2;        /* num = 1 */
printf("%d", sum);          /* num = 1 */

這段代碼的運行次數(shù)函數(shù)是 f(n) = 1 + 1 + 1 ,根據(jù)“推導大O階方法”中的第一條規(guī)則氓扛,把
1 + 1 + 11 替換枯芬,運行次數(shù)函數(shù)變成了 f(n) = 1。該函數(shù)只有常數(shù)項,只需使用規(guī)
則1就可以推導出它即這段代碼的時間復雜度是 O(1) 千所。

假如 sum = (n+1) * n / 2 執(zhí)行3次狂魔,將上面的代碼修改為:

int sum = 0, n = 100;       /* num = 1 */
sum = (n+1) * n / 2;        /* num = 1 */
sum = (n+1) * n / 2;        /* num = 1 */
sum = (n+1) * n / 2;        /* num = 1 */
printf("%d", sum);          /* num = 1 */

這段代碼的運行次數(shù)函數(shù)是 f(n) = 1 + 1 + 1 + 1 + 1 。 按照推導大O階第一條規(guī)則淫痰,用1取代
所有的加法常數(shù)最楷,這段代碼的運行次數(shù)函數(shù)是 f(n) = 1。這段代碼的時間復雜度依然是 f(n) = O(1) 黑界。

所有這類代碼的時間復雜度都是 O(1)管嬉。O(1)叫做常數(shù)階。不存在 O(2) 朗鸠、 O(9) 這類寫法蚯撩。

線性階舉例運用

code-3

int i;
for(i = 0; i < n; i++){
    // 時間復雜度為O(1)的代碼
}

code-3的運行次數(shù)函數(shù)是 f(n) = n * 1。加法常數(shù)為0個烛占,跳過規(guī)則一胎挎。變量n的最高階是 n * 1,無
其他項忆家,跳過規(guī)則二犹菇。n * 1中的系數(shù)本來就是1,也可以直接跳過規(guī)則三芽卿,得到code-3的時間復雜度是
f(n) = O(n)揭芍。

code-4

int i;
for(i = 0; i < n; i++){
    // 時間復雜度為O(1)的代碼
}

int j;
for(j = 0; j < m; j++){
    // 時間復雜度為O(1)的代碼
}

code-4的運行次數(shù)函數(shù)是f(n) = n * 1 + m * 1拿霉。直接跳過規(guī)則一跷叉。n * 1 + m * 1有兩個變量,
但次數(shù)都是1砌烁,任何一項 n * 1m * 1 都可視為最高價筷转,根據(jù)推導規(guī)則二“保留最高階”姑原,得出
運行次數(shù)函數(shù)是f(n) = n * 1f(n) = m * 1。最后根據(jù)規(guī)則三呜舒,得出code-4的時間復雜度是
f(n) = O(n)锭汛。

對數(shù)階舉例運用

code-5

int count = 1;
while(count < n){
    count = count * 2;
    //其他時間復雜度為O(1)的代碼 
}

code-5似乎不能用前面的推導大O階方法來分析時間復雜度,我從《數(shù)據(jù)結構與算法分析》P21找到了分析
"運行時間中的對數(shù)"的一般法則袭蝗。這個一般法則是:

如果一個算法用常數(shù)時間(O(1)將問題的大小削減為其一部分(通常是1/2)唤殴,那么該算法就是 O(log N)
另一方面到腥,如果使用常數(shù)時間只是把問題減少一個常數(shù)(如將問題減少1)眨八,那么這種算法就是 O(N)

code-5中左电,假設 n = 8 ,初始化時,while(count < n) 需要運行8次篓足。經(jīng)過一次循環(huán)后段誊,count變?yōu)?,
循環(huán)需要運行4次栈拖,變?yōu)樵瓉淼囊话肓帷8鶕?jù)那條一般法則,判斷 code-5 的時間復雜度是 O(log N)涩哟。

code-5修改為code-6索赏,

int count = 1;
while(count < n){
    count = count + 2;
    //其他時間復雜度為O(1)的代碼 
}

code-6每次執(zhí)行循環(huán)后,會把問題減少2個常數(shù)贴彼,時間復雜度應為 O(N)潜腻。

若將code-6中的count = count + 2改為code = count - 2,時間復雜度仍然是 O(N)器仗。但我有點理解不了融涣。

平方價舉例運用

code-7

int i, j;   /*1*/
for(i = 0; i < n; i++){ /*2*/
    for(j = 0; j < n; j++){ /*3*/
        //時間復雜度為O(1)的代碼 /*4*/
    }   /*5*/
}   /*6*/

code-7中第二個循環(huán)體的時間復雜度是O(N)。第一個循環(huán)體將第二個循環(huán)體再執(zhí)行N次精钮,時間復雜度變?yōu)?code>O(N2)威鹿。
如果將第二個循環(huán)體中的n改為m,那么code-7的時間復雜度就是O(N*M)轨香。注意忽你,O(N*M)O(N2)都叫做
平方階,二者實質相同臂容。

多層循環(huán)體的時間復雜度就是每層循環(huán)體的運行次數(shù)相乘科雳。

code-8

int i, j;
for(i = 0; i < n; i++){
    for(j = i; j < n; j++){
        //時間復雜度為O(1)的代碼
    }
}

code-8運行次數(shù)是(n+1)*n*n/2。只保留最高階并且去掉它的系數(shù)策橘,時間復雜度是O(N2)炸渡。有些地方理解不了。

code-9

void function(int count){

    int j;
    
    for(j = count; j < n; j++){
    
        printf("%s", "hello,world");
        
    }
}

n++;        /* num = 1 */

function(n);    /* num = n */

int i,j;    /* num = 1 */

for(i = 0; i < n; i++){     /* num = n*n */
    
    function(i);
    
}

for(i = 0; i < n; i++){         /* num = (n+1)*n/2 */
    
    for(j = i; j < n; j++){
        
        printf("%s", "hi");
        
    }
}

code-9的時間復雜度是多少呢丽已?

首先將每行代碼的執(zhí)行次數(shù)標出來蚌堵。

code-9的執(zhí)行次數(shù)(首先忽略掉常數(shù)項)是n + n*n + (n+1)*n/2,計算結果為1.5*n*n + 2*n沛婴。
只保留最高階1.5*n*n吼畏,最后將系數(shù)變?yōu)?,執(zhí)行次數(shù)為n*n嘁灯,時間復雜度為O(N2)泻蚊。

這種方法有不確定性的因素存在,或者說丑婿,在計算執(zhí)行次數(shù)的時候性雄,使用了互相矛盾的方法没卸。

獨立博客地址:chugang.net

重新思考之后,發(fā)現(xiàn)并不存在矛盾秒旋,而是《大話數(shù)據(jù)結構》中推導時間復雜度的方法有小缺陷约计。這個推導
本身就是一種粗略估計,為何在推導過程中有時又在進行精確計算呢迁筛?以code-8為例煤蚌,該書使用了精確
的計算方法。若全部都堅持使用粗略估計計算细卧,那么計算過程是這樣的:code-8中第二個循環(huán)體的運行
次數(shù)是N尉桩,或者抽象為“一個變量”,第一個循環(huán)體的運行次數(shù)也是N或M贪庙,也抽象為“一個變量”蜘犁,整體的運行
次數(shù)為兩個變量相乘,即時間復雜度為O(N2)插勤。這種粗略估計計算方法沽瘦,建立的基礎是:影響循環(huán)執(zhí)行次數(shù)
的變量只有那個與循環(huán)終止條件相關的變量,與起始變量無關农尖。

這種方法析恋,又不能適用于對數(shù)階的時間復雜度推導∈⒖ǎ或許助隧,對數(shù)階中的循環(huán),本來就是一種特殊情況滑沧,不能
采用普通循環(huán)的推導方法并村。此處存疑。*

常見的時間復雜度

直接摘抄《大話數(shù)據(jù)結構》中的有關部分滓技。

常見的時間復雜度
常見的時間復雜度

理解不了這些時間復雜度所耗時間的順序哩牍,應該如何比較它們所耗時間?

獨立博客地址:chugang.net

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末令漂,一起剝皮案震驚了整個濱河市膝昆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌叠必,老刑警劉巖荚孵,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異纬朝,居然都是意外死亡收叶,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門共苛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來判没,“玉大人蜓萄,你說我怎么就攤上這事《咧拢” “怎么了绕德?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長摊阀。 經(jīng)常有香客問我,道長踪蹬,這世上最難降的妖魔是什么胞此? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮跃捣,結果婚禮上漱牵,老公的妹妹穿的比我還像新娘。我一直安慰自己疚漆,他們只是感情好酣胀,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著娶聘,像睡著了一般闻镶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上丸升,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天铆农,我揣著相機與錄音,去河邊找鬼狡耻。 笑死墩剖,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的夷狰。 我是一名探鬼主播岭皂,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼沼头!你這毒婦竟也來了爷绘?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤瘫证,失蹤者是張志新(化名)和其女友劉穎揉阎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體背捌,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡毙籽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了毡庆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坑赡。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡烙如,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出毅否,到底是詐尸還是另有隱情亚铁,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布螟加,位于F島的核電站徘溢,受9級特大地震影響,放射性物質發(fā)生泄漏捆探。R本人自食惡果不足惜然爆,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望黍图。 院中可真熱鬧曾雕,春花似錦、人聲如沸助被。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽揩环。三九已至搔弄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間检盼,已是汗流浹背肯污。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吨枉,地道東北人蹦渣。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像貌亭,于是被迫代替她去往敵國和親柬唯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

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