【手撕數據結構】卸甲時/空間復雜度

目錄

  • 前言
  • 時間復雜度
    • 概念
    • ?O的漸進表?法
    • 小試牛刀
  • 空間復雜度

前言

要想知道什么是空/時間復雜度,就得知道什么是數據結構。

這得分兩層來理解。我們生活中處處存在數據,什么抖音熱點上的國際大事,什么懂的都懂的雍正卸甲等等一系列我們用戶看得到的,就是抖音存儲在后臺服務器的數據。但這些數據都有一個特點,那就是都在抖音的熱搜榜單上,而這個榜單就是結構,保證數據在一個固定的位置里以便用戶瀏覽。

此外有了數據結構,就離不開算法。那么我們剛剛說了,數據結構是把數據有規律的存儲在一個結構中,那么怎么從結構中有效率的存取數據,這就是算法。

時間復雜度

有了算法,就存在時間復雜度和空間復雜度。因為計算機現在的內存越來越大,所以時間復雜度比空間復雜度更顯得重要。所以我們先來了解時間復雜度

概念

時間復雜度,最重要的詞就是時間,這里的時間就是指一個程序運行時的時間,如果時間復雜度越少,那么證明這個算法越好。時間復雜度計算用函數式T(N)表示

那為什么我們不提前算出這個程序的時間復雜度來寫出最優解的代碼呢?這里就涉及到計算機的問題。

  1. 因為程序運?時間和編譯環境和運?機器的配置都有關系,?如同?個算法程序,??個?編譯
    器進?編譯和新編譯器編譯,在同樣機器下運?時間不同。
  2. 同?個算法程序,??個?低配置機器和新?配置機器,運?時間也不同。
  3. 并且時間只能程序寫好后測試,不能寫程序前通過理論思想計算評估。

下面我們來看一段代碼:

// 請計算?下Func1中count語句總共執?了多少
次?
void Func1(int N)
{
int count = 0;
for (int i = 0; i < N ; ++ i)
{
for (int j = 0; j < N ; ++ j)
{
++count;
}
}
for (int k = 0; k < 2 * N ; ++ k)
{
++count;
}
int M = 10;
while (M--)
{
++count;
}
}

這段代碼如果根據count的執行次數來看的話應該是:
T (N) = N2 + 2 ? N + 10
? N = 10 T(N) = 130
? N = 100 T(N) = 10210
? N = 1000 T(N) = 1002010

這時候有人就說,那個int count=0不算嗎;

這里我們就太小看我們的計算機了,我們計算機一秒鐘cpu可以執行上億次,這小小的一次當然可以忽略不計。所以說我們計算的時間復雜度并不準確,只是粗略估計而已,這時候我們就用一個新的符號表示.

?O的漸進表?法

?O符號(Big O notation):是?于描述函數漸進?為的數學符號;這里用來表示估算的時間復雜度。

那么這里還是跟T(N)一樣算嗎,如果是這樣我們就沒必要用另外一個符號來表示了。這里就涉及到算O的規則:

  1. 時間復雜度函數式T(N)中,只保留最?階項,去掉那些低階項,因為當N不斷變?時,低階項對結果影響越來越?,當N?窮?時,就可以忽略不計了。
  2. 如果最?階項存在且不是1,則去除這個項?的常數系數,因為當N不斷變?,這個系數對結果影響越來越?,當N?窮?時,就可以忽略不計了
  3. T(N)中如果沒有N相關的項?,只有常數項,?常數1取代所有加法常數。

那么再來看上面的T(N)=N^ 2 + 2 ? N + 10,這里的最高階是N2所以去掉其他的低階,復雜度就為(ON^2)

小試牛刀

// 計算Func3的時間復雜度?
void Func3(int N, int M)
{
int count = 0;
for (int k = 0; k < M; ++ k)
{
++count;
}
for (int k = 0; k < N ; ++
k)
{
++count;
}
printf("%d\n", count);
}

這里的T(N)=M+N,那我們再來算O(N),這里M和N都是同階,所以不符合第一條規則,也沒有對應第二條和第三條,所以為o(N+M),那么有人就問了,萬一N比M大呢,是不是因該是O(N).這里問題就是,你怎么知道N比M大?萬一是M比N大呢,所以保險起見我們都留下來。

// 計算strchr的時間復雜度?
const char * strchr ( const char* str, int character)
{
const char* p_begin = s;
while (*p_begin != character)
{
if (*p_begin == '\0')
return NULL;
p_begin++;
}
return p_begin;
}

這里我們是查找character在str中的位置,這里我補充一個知識點:

  • 我們的O算的一般是一個算法的最壞情況下的復雜度
    這里就可以分為三個復雜度:
    1.最好情況
    若要查找的字符在字符串第?個位置,則:
    F (N) = 1,復雜度為o(1)

2.平均情況:
若要查找的字符在字符串中間位置,則:
F (N) = N/2,O(N/2)

3.最壞情況
若要查找的字符在字符串最后的?個位置,則:
F (N) = N,O(N)

// 計算BubbleSort的時間復雜度?
void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i-1] > a[i])
{
Swap(&a[i-1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}

在這里插入圖片描述
最壞情況下,又因為保留高階去掉n/2(第一條),忽略系數(第二條),所以為ON^2

void func5(int n)
{
int cnt = 1;
while (cnt < n)
{
cnt *= 2;
}
}

當n=2時,執?次數為1
當n=4時,執?次數為2
當n=16時,執?次數為4
假設執?次數為 x ,則 2
x = n
因此執?次數: x = log n
因此:func5的時間復雜度取最差情況為:
O(log2 ^n)

不同書籍的表??式不同,以上寫法差別不?,我們建議使? log n

空間復雜度

空間復雜度要注意的是,他的計算表示也是用O來表示,并且他的規則與時間復雜度一樣遵守那三條規則

注意

函數運?時所需要的棧空間(存儲參數、局部變量、?些寄存器信息等)在編譯期間已經確定好了,因此空間復雜度主要通過函數在運?時候顯式申請的額外空間來確定

例1:

// 計算BubbleSort的時間復雜度?
void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i-1] > a[i])
{
Swap(&a[i-1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}

函數棧幀在編譯期間已經確定好了,
只需要關注函數在運?時額外申請的空間。
BubbleSort額外申請的空間有
exchange等有限個局部變量,使?了常數個額外空間
因此空間復雜度為 O(1)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43094.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43094.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43094.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

鴻蒙語言基礎類庫:【@ohos.url (URL字符串解析)】

URL字符串解析 說明&#xff1a; 本模塊首批接口從API version 7開始支持。后續版本的新增接口&#xff0c;采用上角標單獨標記接口的起始版本。開發前請熟悉鴻蒙開發指導文檔&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md點擊或者復制轉到。 導入…

【K8s】專題六(5):Kubernetes 穩定性之重啟策略、滾動更新策略

以下內容均來自個人筆記并重新梳理&#xff0c;如有錯誤歡迎指正&#xff01;如果對您有幫助&#xff0c;煩請點贊、關注、轉發&#xff01;歡迎掃碼關注個人公眾號&#xff01; 目錄 一、重啟策略 1、基本介紹 2、資源清單&#xff08;示例&#xff09; 二、滾動更新策略 …

Vue框架引入

vue簡介 1.1.vue是什么?Vue官網 英文官網: https://vuejs.org/中文官網: https://cn.vuejs.org/ vue是一套構建用戶界面的漸進式javascript框架 構建用戶界面:將我們手里拿到的數據通過某種辦法變成用戶可以看見的界面前端工程師的職責:就是在合適的時候發出合適的請求,然后…

展開說說:Android服務之bindService解析

前面兩篇文章我們分別總結了Android四種Service的基本使用以及源碼層面總結一下startService的執行過程&#xff0c;本篇繼續從源碼層面總結bindService的執行過程。 本文依然按著是什么&#xff1f;有什么&#xff1f;怎么用&#xff1f;啥原理&#xff1f;的步驟來分析。 b…

Splunk Enterprise 任意文件讀取漏洞(CVE-2024-36991)

文章目錄 前言漏洞描述影響版本漏洞復現POC批量檢測-nuclei腳本 修復建議 前言 Splunk Enterprise 是一款強大的機器數據管理和分析平臺&#xff0c;能夠實時收集、索引、搜索、分析和可視化來自各種數據源的日志和數據&#xff0c;幫助企業提升運營效率、增強安全性和優化業務…

數據庫作業3

DELETE FROM student WHERE grade IS NULL; 一、數據庫操作部分 1. 向 student 表中添加一條新記錄&#xff1a; INSERT INTO student (id, name, grade) VALUES (1, monkey, 98.5); 2. 向 student 表中添加多條新記錄&#xff1a; INSERT INTO student (id, name, grade) V…

【MYSQL】如何解決 bin log 與 redo log 的一致性問題

該問題問的其實就是redo log 的兩階段提交 為什么說redo log 具有崩潰恢復的能力 MySQL Server 層擁有的 bin log 只能用于歸檔&#xff0c;不足以實現崩潰恢復&#xff08;crash-safe&#xff09;&#xff0c;需要借助 InnoDB 引擎的 redo log 才能擁有崩潰恢復的能力。所謂崩…

PHP的發展歷程以及功能使用場景

PHP的發展歷程 PHP的發展歷程可以追溯到1994年&#xff0c;由丹麥計算機程序員拉斯穆斯勒多夫&#xff08;Rasmus Lerdorf&#xff09;出于個人網站統計訪問者信息的需求而創建。以下是PHP發展歷程中的幾個重要里程碑&#xff1a; 初創階段&#xff08;1994-1995年&#xff09…

二刷力扣——單調棧

739. 每日溫度 單調棧應該從棧底到棧頂 是遞減的。 找下一個更大的 &#xff0c;用遞減單調棧&#xff0c;就可以確定在棧里面的每個比當前元素i小的元素&#xff0c;下一個更大的就是這個i&#xff0c;然后彈出并記錄&#xff1b;然后當前元素i入棧&#xff0c;仍然滿足遞減…

數學基礎 -- 三角學

三角學 三角學&#xff08;Trigonometry&#xff09;是數學的一個分支&#xff0c;主要研究三角形的邊長與角度之間的關系。三角學在幾何學、物理學、工程學等多個領域中有廣泛的應用。以下是三角學的一些基本概念和公式&#xff1a; 基本概念 直角三角形&#xff1a;一個角…

Java進階----繼承

繼承 一.繼承概述 繼承是可以通過定義新的類&#xff0c;在已有類的基礎上擴展屬性和功能的一種技術. 案例&#xff1a;優化 貓、狗JavaBean類的設計 狗類&#xff1a;Dog 屬性&#xff1a;名字 name&#xff0c;年齡 age 方法&#xff1a;看家 watchHome()&#xff0c;Gett…

防抖和字節流

防抖&#xff08;Debouncing&#xff09;和字節流&#xff08;Byte Stream&#xff09;是兩個不同的概念&#xff0c;分別在編程和數據傳輸領域中使用。 防抖&#xff08;Debouncing&#xff09; 防抖是一種在前端開發中常用的技術&#xff0c;用于控制事件處理函數的執行頻率…

Android多開應用軟件系統設計

設計一個支持Android多開應用的軟件系統&#xff0c;主要涉及到以下幾個關鍵技術點和設計考慮&#xff1a; 1. 虛擬化技術 容器技術&#xff1a;與傳統的虛擬機不同&#xff0c;可以采用更輕量級的容器技術&#xff0c;為每個應用實例創建獨立的運行環境。這包括分配獨立的用…

Ubuntu配置sendmail client,用sendmail命令來發送郵件

參考文檔 https://mailoutgoing.com/support/mailrelay/sendmail.html https://www.sendmail.org/~ca/email/auth.html https://docs.oracle.com/en/operating-systems/oracle-linux/6/admin/configure-sendmail.html 總結 1、ubuntu環境下&#xff0c;sendmail服務位于/etc/i…

HTTP 請求走私漏洞詳解

超詳細的HTTP請求走私漏洞教程&#xff0c;看完還不會你來找我。 1. 簡介 HTTP請求走私漏洞&#xff08;HTTP Request Smuggling&#xff09;發生在前端服務器&#xff08;也稱代理服務器&#xff0c;一般會進行身份驗證或訪問控制&#xff09;和后端服務器在解析HTTP請求時&…

上位機圖像處理和嵌入式模塊部署(mcu項目2:串口日志記錄器)

【 聲明&#xff1a;版權所有&#xff0c;歡迎轉載&#xff0c;請勿用于商業用途。 聯系信箱&#xff1a;feixiaoxing 163.com】 淘寶上面有一個商品蠻好玩的&#xff0c;那就是日志記錄器。說是記錄器&#xff0c;其實就是一個模塊&#xff0c;這個模塊的輸入是一個ttl串口&am…

利用Python進行數據分析PDF下載經典數據分享推薦

本書由Python pandas項目創始人Wes McKinney親筆撰寫&#xff0c;詳細介紹利用Python進行操作、處理、清洗和規整數據等方面的具體細節和基本要點。第2版針對Python 3.6進行全面修訂和更新&#xff0c;涵蓋新版的pandas、NumPy、IPython和Jupyter&#xff0c;并增加大量實際案例…

Docker Desktop如何換鏡像源?

docker現在很多鏡像源都出現了問題,導致無法拉取鏡像,所以找到一個好的鏡像源,尤為重要。 一、阿里鏡像源 經過測試,目前,阿里云鏡像加速地址還可以使用。如果沒有阿里云賬號,需要先注冊一個賬號。 地址:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 二…

基于Java技術的B/S模式書籍學習平臺

你好&#xff0c;我是專注于計算機科學領域的學姐碼農小野。如果你對書籍學習平臺開發感興趣或有相關需求&#xff0c;歡迎私信聯系我。 開發語言&#xff1a; Java 數據庫&#xff1a; MySQL 技術&#xff1a; B/S模式、Java技術 工具&#xff1a; Eclipse、Navicat、Mave…

【Go】函數的使用

目錄 函數返回多個值 init函數和import init函數 main函數 函數的參數 值傳遞 引用傳遞&#xff08;指針&#xff09; 函數返回多個值 用法如下&#xff1a; package mainimport ("fmt""strconv" )// 返回多個返回值&#xff0c;無參數名 func Mu…