1. 程式人生 > >時間複雜度(演算法分析)

時間複雜度(演算法分析)

演算法分析

在現在這個資訊爆炸的時代,處理資料的量也越來越大。所以人們在用計算機來解決日常生活生產的問題的時候難免會有這樣的疑問。
我的程式會執行多長時間?
我的程式會耗多少的記憶體?
這次我們就來簡單討論一下第一個“我的程式會執行多長時間?”。

執行時間

要知道一個程式的執行時間,最簡單的方法就是計時啦,簡單粗暴。
但是這自然要問,我不可能每一次都用個秒錶去測量吧,而且程式的執行時間會受到多種因素的干擾(作業系統,計算機的效能引數等等),所以就算用秒錶測量得出的數值也不具有什麼意義。
所以自然我們要用一種相對的測量方法,我們可以通過計算一個物件被操作的次數來計算程式相對的執行時間。
下面我們分析一個簡單的例子,看看怎樣來估計程式的執行時間

public int sum(int[] a,int[] b){
    int sum=0;
    for(int i =0; i<a.length; i++){
        for(int j=0; j<b.length; j++){
            sum=sum+a[i]+b[j];
        }
    }
    return sum;
}

分析上面的求和程式碼,我們可以看到a中的每一個元素與每一個b中的元素求和,假設陣列的長度(a.length)比較大,而且兩陣列長度近似相等(n=a.length=b.length)。那麼明顯每個陣列被訪問的次數為n

2,兩個陣列就是2n2。現在我們假定執行時間就是輸入資料的規模大小(n)的函式:T(n)=2n2。而且事實也的確是這樣。
也可以用大O記法,記作O(n2)(通常忽略低階項和常數項),叫作時間複雜度。

這樣就給出了一個我們估計程式執行時間的相對參考量,雖然並不能非常準確的計算程式的執行時間。但是至少也給出來程式的執行時間和輸入資料的規模的函式變化規律。就像上面的例子執行時間跟輸入資料的規模成平方增長。

常用演算法的時間複雜度

這裡寫圖片描述
上圖取自維基百科,上面列出了常用的演算法的時間複雜度列表。

數學定義

在最後給出演算法分析的數學基礎,數學定義。

大O記號

O(g(n))={ f(n): 存在正常數c和n0,使所有n>n0,有0≦f(n)≦c*g(n)}
上面的定義說明了O(g(n))是一個函式集合,集合裡面的函式滿足g(n)的常數倍是函式f(n)的一個上界,即f(n)有上界。

Ω記號

Ω(g(n))={ f(n):存在正常數c和n0,使所有n>n0,有0≦ c*g(n)≦f(n)}
上面的定義說明集合裡面的函式滿足g(n)的常數倍是函式f(n)的一個下界,即f(n)有下界。

Θ記號

Θ(g(n)),當且僅的,f(n)屬於O(g(n))和Ω(g(n))。
可見Θ是更強的形式。Θ蘊含大O和Ω。
有了這個數學基礎後就可以證明當分析程式的成本的時候,大多時候可以忽略掉低次項和常數相。

總結

當然演算法是一門很大的學科,絕不僅只有這些內容。如果各位同學有興趣可以看一下相關的教材。

相關推薦

時間複雜演算法分析

演算法分析 在現在這個資訊爆炸的時代,處理資料的量也越來越大。所以人們在用計算機來解決日常生活生產的問題的時候難免會有這樣的疑問。 我的程式會執行多長時間? 我的程式會耗多少的記憶體? 這次我們就來簡單討論一下第一個“我的程式會執行多長時間?”。

LeetCode 20. Valid Parentheses 時間複雜O( n​​​​​​)

時間複雜度(O( n​​​​​​)) class Solution { public: bool isValid(string s) { if(s.length()%2==1)return false; vector<char&

計算時間複雜--簡單版

步驟: 1、找到執行次數最多的語句 2、語句執行語句的數量級 3、用O表示結果 計算時間複雜度的3個出發點,掌握這三個出發點,那麼一向搞不懂的時間複雜度就可以迎刃而解啦。 然後: 1、用常數1取代執行時間中的所有加法常數 2、在修改後的執行次數函式中,只保留最高

資料結構十分鐘搞定時間複雜演算法時間複雜【轉】

我們假設計算機執行一行基礎程式碼需要執行一次運算。 int aFunc(void) { printf("Hello, World!\n"); // 需要執行 1 次 return 0; // 需要執行 1 次 } 那麼上面這個

十分鐘搞定時間複雜演算法時間複雜

我們假設計算機執行一行基礎程式碼需要執行一次運算。 int aFunc(void) { printf("Hello, World!\n"); // 需要執行 1 次 return 0; // 需要執行 1 次 } 那麼上面這個方法

排序演算法--時間複雜平均時間,最壞情況、空間複雜

1、時間複雜度:一般情況下,演算法中基本操作重複執行的次數是問題規模n的某個函式f(n),演算法的時間量度記作:                                            

2-路歸併排序C程式碼及其時間複雜的具體分析

時間複雜度:        這是一個遞推公式(Recurrence),我們需要消去等號右側的T(n),把T(n)寫成n的函式。其實符合一定條件的Recurrence的展開有數學公式可以套,這裡我們略去嚴格的數學證明,只是從直觀上看一下這個遞推公式的結果。當n=1時可以設T(1)=c1,當n>1

LeetCode 49. Group Anagrams 時間複雜O(k*n)

時間複雜度(O( k*n)) class Solution { public: vector<vector<string>> groupAnagrams(vector<string>& strs) { un

看動畫輕鬆理解時間複雜

原文連結:看動畫輕鬆理解時間複雜度(一) 演算法(Algorithm)是指用來操作資料、解決程式問題的一組方法。對於同一個問題,使用不同的演算法,也許最終得到的結果是一樣的,比如排序就有前面的十大經典排序和幾種奇葩排序,雖然結果相同,但在過程中消耗的資源和時間卻會有很大的區別,比如快速排序與猴子排

看動畫輕鬆理解時間複雜

    上篇文章講述了與複雜度有關的大 O 表示法和常見的時間複雜度量級,這篇文章來講講另外幾種複雜度: 遞迴演算法的時間複雜度(recursive algorithm time complexity),最好情況時間複雜度(best case time complexity)、最壞情況

雜談——如何合併兩個有序連結串列時間複雜為O(n)

假設本帥博主有連結串列arr1: int[] arr1 = {1,3,6,8,23,34,56,77,90}; 連結串列arr2: int[] arr2 = {-90,34,55,79,87,98,123,234,567}; 我要如何才能夠合併這兩個有序連結串列,使得合併後的連結串列

對公司幾萬名員工按年齡排序時間複雜為O(N)

【0】 目錄 【1】題目 【2】分析 【3】測試程式碼 【4】測試結果 【1】題目: 面試官: 請實現一個排序演算法,要求時間複雜度為O(N) 應聘者:請問對什麼數字進行排序,共有多少數字? 面試官:我們想對公司所有員工按年齡排序,我們公司共有幾

最長遞增子序列,時間複雜Onlogn

package com.kailong.datastures; import java.util.Arrays; /** * Created by Administrator on 2017/4/17. * 最長遞增子序列 */ public class Find

堆處理海量資料----求前k個最小的數--時間複雜n * log k

通過閱讀July的書籍,發現裡面求前k個最小數有很多方法。但在面對處理海量資料處理的時候,不能 把全部資料都放在電腦記憶體中。這時用堆來處理,並把資料放在外存中,通過讀取檔案的方式來讀取。感覺該方法十分巧妙,時間複雜度(n*log k)。程式碼如下: #include&l

演算法的空間複雜空間代價

空間代價 時間代價是相對於處理某個資料結構的演算法而言的,而空間代價是相對於資料結構本身而言的。 例1:一個包含n個整數的一維陣列空間代價為多少? 如果每個整數佔用c位元組,則整個陣列

373-時間複雜表示式求值

在 ACM 裡面,計算複雜度是一項非常重要的事情,常見的複雜度格式有三種: O(n) O(lg(n)) O(sqrt(n)) 一個演算法往往有多種解法,每種解法的複雜度有上述常見的的複雜度組合成,例如排序的兩種演算法: 快速排序: 時間複雜度為

LeetCode 39. Combination Sum 時間複雜O( n^k​​​​​​​)

時間複雜度(O( n^k)),思想,DFS 深度遍歷 class Solution { public: vector<vector<int>> combinationSum(vector<int>& candidates,

無空間複雜無棧的非遞迴二叉樹中序遍歷

常見的二叉樹非遞迴演算法都是用棧儲存訪問路徑上的結點,這樣使空間複雜為o(n),其中n為樹最大深度。空間複雜度為o(1)的演算法並沒有以犧牲時間複雜度為代價,它只是巧妙的運用葉子結點左右孩子指標為空這一事實,將所有的葉子組成一鏈棧用於儲存回退資訊,其中葉子結點的lchild域

最長遞增子序列 時間複雜:O(NlogN

假設存在一個序列d[1..9] = 2 1 5 3 6 4 8 9 7,可以看出來它的LIS長度為5。 下面一步一步試著找出它。 我們定義一個序列B,然後令 i = 1 to 9 逐個考察這個序列。 此外,我們用一個變數Len來記錄現在最長算到多少了 首先,把d[1]有序地放

演算法導論 第二章:演算法入門 筆記 插入排序、迴圈不變式、演算法分析、最好和最壞時間複雜、選擇排序、分治法、合併排序

插入排序: 排序問題的定義如下: 輸入:N個數{a1, a2,..., an }。 輸出:輸入序列的一個排列{a'1 ,a'1 ,...,a'n },使得a'n <=a' n<=...<