算法概念以及算法簡單分析

  隨着互聯網技術的發展,python這門語言被普遍使用,特別是在大數據與機器學習領域,他的優點特別明顯。我相信,在不久的未來,python這門年輕而優美的語言也將會受到更多的追捧,會pthon編程的人將愈來愈吃香。如今本身也必須順應時代發展,也開始研究數據算法與結構,機器學習相關的東西了。python

  這是個人第一篇關於數據方面的文章,也是這個博客帳號的第一篇文章。文章內容雖然簡單,但對於初學者來講卻很實用,相信經過此篇文章,必定會有所收穫。今天的主要內容時主要分享:算法與數據先關的概念,。算法

一.問題的引入:編程

  先來看一道題,經過這道題,咱們先體會一下算法思想在計算機編程中的使用:數據結構

  若是 a+b+c=1000,且 a^2+b^2=c^2(a,b,c 爲天然數),如何求出全部a、b、c可能的組合?機器學習

  如今咱們先用一段簡單的python代碼來實現這個功能,代碼以下:    函數

    import time

    start_time = time.time()

    # 此處是三次for循環嵌套
    for a in range(0, 1001):
        for b in range(0, 1001):
            for c in range(0, 1001):
                if a**2 + b**2 == c**2 and a+b+c == 1000:
                    print("a, b, c: %d, %d, %d" % (a, b, c))

    end_time = time.time()
    print("endtime: %f" % (end_time - start_time))
    print("end!")

   運行結果以下:性能

    a, b, c: 0, 500, 500
    a, b, c: 200, 375, 425
    a, b, c: 375, 200, 425
    a, b, c: 500, 0, 500
    endtime: 214.583347
    end!

  這段功能與邏輯簡單代碼,特就涉及了計算機編程中一個最基本的算法思想,下面咱們想講解一下算法概念吧。學習

二.算法:大數據

算法的概念spa

   算法是計算機處理信息的本質,由於計算機程序本質上是一個算法來告訴計算機確切的步驟來執行一個指定的任務。通常地,當算法在處理信息時,會從輸入設備或數據的存儲地址讀取數據,把結果寫入輸出設備或某個存儲地址供之後再調用。

  算法是獨立存在的一種解決問題的方法和思想。

  對於算法而言,實現的語言並不重要,重要的是思想。

  算法能夠有不一樣的語言描述實現版本(如C描述、C++描述、Python描述等),咱們如今是在用Python語言進行描述實現。

算法的五大特性

  1. 輸入: 算法具備0個或多個輸入
  2. 輸出: 算法至少有1個或多個輸出
  3. 有窮性: 算法在有限的步驟以後會自動結束而不會無限循環,而且每個步驟能夠在可接受的時間內完成
  4. 肯定性:算法中的每一步都有肯定的含義,不會出現二義性
  5. 可行性:算法的每一步都是可行的,也就是說每一步都可以執行有限的次數完成

  對什麼是算法有了瞭解以後,仍是剛纔的問題,咱們只將剛纔的那段代碼部分改動,看看最後的輸出時間又有什麼不一樣?

  改動後的代碼以下: 

  import time

  start_time = time.time()

  # 此處如今爲兩次for循環嵌套
  for a in range(0, 1001):
      for b in range(0, 1001-a):
          c = 1000 - a - b       # 原來c的值是用for循環遍從來取,如今咱們將c直接用a、b 表示
          if a**2 + b**2 == c**2:
              print("a, b, c: %d, %d, %d" % (a, b, c))

  end_time = time.time()
  print("endtime: %f" % (end_time - start_time))
  print("end!")

 輸出的結果爲:  

  a, b, c: 0, 500, 500
  a, b, c: 200, 375, 425
  a, b, c: 375, 200, 425
  a, b, c: 500, 0, 500
  endtime: 0.182897
  end!

   如今咱們將這兩次代碼運行的時間作個比較,就能發現,對於同一問題,當算法不一樣時,代碼的運行結果差別也很是大。

  下面咱們進一步瞭解一下算法效率 

算法效率衡量

執行時間反應算法效率

   對於同一問題,咱們給出了兩種解決算法,在兩種算法的實現中,咱們對程序執行的時間進行了測算,發現兩段程序執行的時間相差懸殊(214.583347秒相比 於0.182897秒),由此咱們能夠得出結論:實現算法程序的執行時間能夠反應出算法的效率,即算法的優劣。

單靠時間值絕對可信嗎?

  假設咱們將第二次嘗試的算法程序運行在一臺配置古老性能低下的計算機中,狀況會如何?極可能運行的時間並不會比在咱們的電腦中運行算法一的214.583347秒快多少。

  單純依靠運行的時間來比較算法的優劣並不必定是客觀準確的!

  程序的運行離不開計算機環境(包括硬件和操做系統),這些客觀緣由會影響程序運行速度並反應在程序的執行時間上。那麼如何才能客觀評判一個算法的優劣呢?

時間複雜度與「大O記法」

  咱們假定計算機執行算法每個基本操做的時間是固定的一個時間單位,那麼有多少個基本操做就表明會花費多少時間單位。顯然對於不一樣的機器環境而言,確切的單位時間是不一樣的,可是對於算法進行多少個基本操做(即花費多少時間單位)在規模數量級上倒是相同的,由此能夠忽略機器環境的影響而客觀的反應算法的時間效率。

對於算法的時間效率,咱們能夠用「大O記法」來表示。

「大O記法」:對於單調的整數函數f,若是存在一個整數函數g和實常數c>0,使得對於充分大的n總有f(n)<=c*g(n),就說函數g是f的一個漸近函數(忽略常數),記爲f(n)=O(g(n))。也就是說,在趨向無窮的極限意義下,函數f的增加速度受到函數g的約束,亦即函數f與函數g的特徵類似。

時間複雜度:假設存在函數g,使得算法A處理規模爲n的問題示例所用時間爲T(n)=O(g(n)),則稱O(g(n))爲算法A的漸近時間複雜度,簡稱時間複雜度,記爲T(n)

如何理解「大O記法」

對於算法進行特別具體的細緻分析雖然很好,但在實踐中的實際價值有限。對於算法的時間性質和空間性質,最重要的是其數量級和趨勢,這些是分析算法效率的主要部分。而計量算法基本操做數量的規模函數中那些常量因子能夠忽略不計。例如,能夠認爲3n2和100n2屬於同一個量級,若是兩個算法處理一樣規模實例的代價分別爲這兩個函數,就認爲它們的效率「差很少」,都爲n2級。

最壞時間複雜度

分析算法時,存在幾種可能的考慮:

  • 算法完成工做最少須要多少基本操做,即最優時間複雜度
  • 算法完成工做最多須要多少基本操做,即最壞時間複雜度
  • 算法完成工做平均須要多少基本操做,即平均時間複雜度

對於最優時間複雜度,其價值不大,由於它沒有提供什麼有用信息,其反映的只是最樂觀最理想的狀況,沒有參考價值。

對於最壞時間複雜度,提供了一種保證,代表算法在此種程度的基本操做中必定能完成工做。

對於平均時間複雜度,是對算法的一個全面評價,所以它完整全面的反映了這個算法的性質。但另外一方面,這種衡量並無保證,不是每一個計算都能在這個基本操做內完成。並且,對於平均狀況的計算,也會由於應用算法的實例分佈可能並不均勻而難以計算。

所以,咱們主要關注算法的最壞狀況,亦即最壞時間複雜度。

時間複雜度的幾條基本計算規則

  1. 基本操做,即只有常數項,認爲其時間複雜度爲O(1)
  2. 順序結構,時間複雜度按加法進行計算
  3. 循環結構,時間複雜度按乘法進行計算
  4. 分支結構,時間複雜度取最大值
  5. 判斷一個算法的效率時,每每只須要關注操做數量的最高次項,其它次要項和常數項能夠忽略
  6. 在沒有特殊說明時,咱們所分析的算法的時間複雜度都是指最壞時間複雜度

空間複雜度

相似於時間複雜度的討論,一個算法的空間複雜度S(n)定義爲該算法所耗費的存儲空間,它也是問題規模n的函數。

漸近空間複雜度也經常簡稱爲空間複雜度。

空間複雜度(SpaceComplexity)是對一個算法在運行過程當中臨時佔用存儲空間大小的量度。

算法的時間複雜度和空間複雜度合稱爲算法的複雜度。

 

如今咱們已經對算法以及算法的表示方法有了瞭解,如今咱們用大O表示法來分析一下剛纔那兩個代碼,看看到底爲何不一樣算法會致使結果差別很是大了?

三:算法分析:

  第一段代碼的核心部分: 

  for a in range(0, 1001):
      for b in range(0, 1001):
          for c in range(0, 1001):
              if a**2 + b**2 == c**2 and a+b+c == 1000:
                  print("a, b, c: %d, %d, %d" % (a, b, c))  

  時間複雜度:

    T(n) = O(n*n*n) = O(n3)

  第二段代碼的算法核心部分:

  for a in range(0, 1001):
      for b in range(0, 1001-a):
          c = 1000 - a - b
          if a**2 + b**2 == c**2:
              print("a, b, c: %d, %d, %d" % (a, b, c))

  時間複雜度:

    T(n) = O(n*n*(1+1)) = O(n*n) = O(n2)

  因而可知,咱們嘗試的第二種算法要比第一種算法的時間複雜度好多的

四.常見時間複雜度:

  常見時間複雜度之間的關係:

  

    所消耗的時間從小到大

    O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)

 

到此,關於算法基礎知識已經介紹完畢,但願看了以後讀者可以有所收穫。

 

若是感受這篇文章還不錯的話,能夠關注我,後期還會陸續發送數據結構方面的文章,但願能夠更多的幫助到大家!

相關文章
相關標籤/搜索