前言:我們到底該不該學習算法與數據結構?
1、真的應該學習
這個問題本身就不是個問題,所有人都在強調數據結構與算法比較重要,但是好像平時也沒用到,無法直觀的去感受它的重要性,於是把學習重心放在了常見的哪些框架身上,似乎只要熟悉了哪些框架的API,編程就會所向披靡。
我舉一個我自身的例子,我本科期間想做一個APP,主要是在線預約的功能,既然是在線預約,用戶多了之後那就需要排隊,當時也不管三七二十一,不管哪種結構,那就先試試ArrayList,當然這種數據結構也能解決,但是當真正操作其增刪改查的時候才發現ArrayList確實是比較麻煩一點。
在網上開始問各種大佬,統一回復的一句話是,你現在學數據結構了嗎?你數據結構咋學的?現在想想真的是留下啦悔恨的眼淚。
既然數據結構與算法重要,到底哪個地方重要呢?下面就來說說:
2、重要性體現
第一:面試
面試確實是第一個體現的點,因為你會發現,面試外企的時候他們第一件事就是啥都不問,上來就是幾道算法題。包括國內的字節跳動。現在的阿里、騰訊、華為、美團。凡是大家知道的那些大廠基本上上來就是先敲代碼。可以看出國內外大廠對於算法與數據結構的看重。
第二:工作
現在的大廠api框架基本上背後的邏輯就是基於算法實現的。其實算法的種類有很多,比如說機器學習、神經網絡算法,還有java中的排序算法,網際網路的商品推薦、股票預測其背後的邏輯都是算法。就算是熟悉的那些框架,背後的邏輯也是數據結構與算法。我們敲代碼解決問題的過程當中也是算法的集中體現。
第三:學習
學習數據結構與算法的目的,別人我不知道,對我目前來說,是想了解哪些常見框架,常見機制背後的運行邏輯。進而為以後創造一個更加強大的產品做鋪墊。任何一個新東西,都是先了解,再模仿,最後再創造的過程。
第四:應付學業
我之前大學學習這門課的時候,學分比重還是比較大的,好幾年過去了,不知道現在變沒變。不過最起碼考研或者是期末考試,這門課都是必須要學習的一門課。可見學校也比較重視。
一、算法與數據結構到底是個什麼東東?
在這裡我不想去解釋哪些常見的名詞了,像什麼是數據項、數據對象、元素等等這些概念。稍微有點基礎的人,對這些概念都應該很清楚,畢竟都是中國人。我主要想說一下,我們到底該如何理解數據結構與算法。
1、什麼是數據結構?
高中的時候都學習過化學,什麼水的結構,碳原子的結構,這些分子、原子之間不是雜亂無章的,我們總是可以歸納分析出一些規律。對於計算機中的數據元素而言,這些數據元素也不是孤立的,總是有一種或者是幾種的內在聯繫。
數據結構:數據元素相互之間一種或者多種關係的表示
既然數據元素之間有某種關係,那這種關係到底是什麼呢?這裡直接總結了一下。
可以看出分兩類,表示了這些數據元素之間的關係。我們在學習數據結構的時候,其實就是學習這些數據元素到底有哪些關係。
2、什麼是算法
宋丹丹和趙本山有過一個小品,說如何把大象關進冰箱裡。第一步先把冰箱門打開,第二步把大象裝進去,第三步,把冰箱門關上。整個簡單的流程完美的體現了算法的思想。標準定義:
算法:解決問題的步驟的描述
就這麼幾個字,其實就是描述過程的。當然解決問題的方法有很多,因此算法也有很多種,就比說我們常見的排序算法,就簡簡單單為了從小到大排序,哪些科學家們活活的搞出了十幾種。每一種排序方式都是一個算法。
3、數據結構與算法的關係(重點)
我們經常會聽到有人說:程序=算法+數據結構,某位大佬科學家就提出了這幾個字還得了圖靈獎。大學的時候知道這件事還讓我一度懷疑圖靈獎也不過如此。嘿嘿,不過現在不敢說了,看的越多,越覺得這個簡單地公式蘊含了無數的道理。
既然是討論他們之間的關係。我們再來看個例子,畢竟例子各位才理解的更加清楚。假如我國要在多個城市之間新建一條高鐵。要求是能夠連結多個城市,而且成本最低。OK,好了,現在就這麼個需求,我們來分析。
第一目的:修建鐵路
第二要求:連通所有城市,成本最低。
我們一下子就能想到這是一個最小生成樹問題,假如把每一個城市看成一個點,把城市之間的成本看成連線數字,就是找出來一個聯通線。
目的其實就是為了找上圖中的那條黑線。這裡不是專門講這個知識體系的。現在我們使用流程圖看看,如果遇到了一個問題,我們是如何去使用程序去解決的。
從上圖可以看出,為了要解決一個問題,首先我們要分析問題,然後確定解決思路,接下來設計或者是選擇已有的算法,再然後就是確定實現的數據結構,最後就是代碼的實現與優化。
數據結構在其中的位置可以看出,是為了更好地實現某種或者是某類算法。在討論這門課的時候也會結合在一起去學習。
二、學習數據結構與算法我們最應該關注什麼?
如果我們想要學好數據結構與算法,首先腦海中要時刻記住兩個關鍵詞彙,時間效率和空間效率。這個兩個詞彙貫穿了整個數據結構與算法的知識體系。
數據結構可以助算法實現問題提供基礎,算法為了解決某一問題必須要時間夠快,空間足夠節省。就好比我們為了能夠在茫茫人海當中找尋另一半一樣。首先時間要足夠快,不能一個一個找,然後我們不可能把茫茫人海所有人的全部信息全給保存了,所以空間上還要足夠節省。
那什麼是時間效率和空間效率呢?通俗的理解就是:我們使用兩個不同的程序去解決同一個問題,時間短的說明時間效率高,消耗空間小的說明空間效率高。
我們在研究數據結構與算法的時候,其實就是選擇不同的數據結構和不同的算法解決某一問題的同時儘可能的提升計算機的時間效率和空間效率。
1、首先看時間複雜度:
想要了解時間複雜度,就需要先了解時間頻度。一個算法花費的時間與算法中語句的執行次數成正比例,哪個算法中語句執行次數多,它花費時間就多。一個算法中的語句執行次數稱為語句頻度或時間頻度。記為T(n)。
說白了時間複雜度就是描述時間的規模,比如說時間頻度是T(n),時間複雜度就是O(n)。時間頻度是T(n+n)的時候,時間複雜度還是O(n)。也就是他的時間規模就是n這個層次了。記作T(n)=O(f(n)),稱O(f(n)) 為算法的漸進時間複雜度,簡稱時間複雜度**。
常見的算法的時間 複雜度之間的關係為:
O(1)<O(logn)<O(n)<O(nlog n)<O(n2)<O(2n)<O(n!)<O(nn)
舉個例子吧:
a=0; //(1)for(i=1;i<=n;i++) //(2)for(j=1;j<=n;j++) //(3) a++; //(4)
語句(1)執行1次,
語句(2)執行n次
語句(3)執行n2次
語句(4)執行n2次
T(n) = 1+n+2n2= O(n2)
2、空間複雜度
空間複雜度就比較容易理解了,空間複雜度是對一個算法在運行過程中臨時佔用存儲空間大小的一個量度,同樣反映的是一個空間規模,我們用 S(n) 來定義。
空間複雜度比較常用的有:O(1)、O(n)、O(n),
三、結論
在本文中,首先討論了數據結構與算法的重要性,然後給出了數據結構與算法的理解,最後就是在學習數據結構與算法時,我們最應該關注的點。其中通過數據結構與算進的關係解決某一問題的流程是重點。在以後的文章中,也會慣用這一思路。這個思路是我在刷了力扣幾百道題時總結出來的。
舉個例子來說一下:
面試中經常會遇到一道題,那就是實現LRU(最近最久未使用)。我們按照上面的流程結構可以很清楚的把問題給解決掉,而不是死記硬背哪些現有的代碼,比如
第一步分析問題,問題是實現最近最久未使用的算法,我們可以畫圖來看一下到底是個什麼問題,然後就是確定算法,比如說第一步我們該幹嘛,第二步該幹嘛等等。接下來確定數據結構的時候,比如說可以自定義Node實現,還有java中為我們提供的LinkedHashMap等等。最後就是根據數據結構的特點通過我們分析的算法流程去實現。
這樣是不是有點清晰了。本專欄將持續推出。也祝你在接下來的日子裡更加靈活運用。