前端工程师算法(一)
算法是指解題方案的準(zhǔn)確而完整的描述,是一系列解決問(wèn)題的清晰指定,算法代表著用系統(tǒng)的方法描述解決問(wèn)題的策略機(jī)制。這個(gè)解釋來(lái)源于百度,對(duì)于入門來(lái)說(shuō)這個(gè)解釋等于白說(shuō)了,你的一臉懵逼我懂,大神略過(guò)。
- 說(shuō)人話
- 算法
- 你需要了解的算法是什么?
開始了解算法就應(yīng)該對(duì)程序有一些認(rèn)識(shí)和理解了,其實(shí)我們所有的程序可以理解為算法加數(shù)據(jù)結(jié)構(gòu)。撇開數(shù)據(jù)結(jié)構(gòu)不談,我們?nèi)粘懙拇a如if-else、for(...)等就是算法。在數(shù)學(xué)里加減乘除是算法,方程公式,幾何公式,乃至高數(shù)也都是算法,而我們的if-else、for(...)就相當(dāng)于數(shù)學(xué)中的加減乘除這種級(jí)別的算法,當(dāng)然在程序里也有加減乘除,同樣也是算法。
但是我們?nèi)粘K磉_(dá)的算法和算法通常的說(shuō)法有一些區(qū)別,我們?nèi)粘1磉_(dá)的算法基本上都是特指一些特殊的算法,這些特殊的算法就相當(dāng)于數(shù)學(xué)中的高數(shù)級(jí)別(不是指難度)。這些算法的特殊性并非其難度,而是具備通用性、高效(空間和時(shí)間)、解決特定問(wèn)題的程序。
前端常用算法之?dāng)?shù)組查重算法
?在前端編程中查重是比較常見的應(yīng)用,以數(shù)組查重為例,通常的思路是通過(guò)嵌套循環(huán),讓每個(gè)值與其他每個(gè)值進(jìn)行逐個(gè)對(duì)比。思路有了,我們就來(lái)實(shí)現(xiàn)以下:
var arr = [8,4,79,38,2,67,4,19,8,13,47,68,37,13,48,2]; var cont = 0;//記錄比較次數(shù) for(var i = 0; i < arr.length; i++){for(var j = 0; j < arr.length; j++){if(arr[i] == arr[j] && i != j){//'i != j'-->排除與自己比較 console.log(arr[i]);}cont ++;//累計(jì) } } console.log(cont);//256這個(gè)查重算法可以說(shuō)基本就實(shí)現(xiàn)了,因?yàn)榻鉀Q了特定問(wèn)題:找到重復(fù)的元素。但是這個(gè)算法并不是我們真正需要的算法,因?yàn)檫@樣對(duì)比出現(xiàn)了很多重復(fù),浪費(fèi)很多計(jì)算資源和時(shí)間,所以這個(gè)算法需要改進(jìn)。
改進(jìn)的目的就是消除重復(fù)對(duì)比,從數(shù)組的有序性我們可以知道,每一次內(nèi)部循環(huán)不需要從頭開始對(duì)比,因?yàn)榍懊嬉呀?jīng)對(duì)比過(guò)了,所以改進(jìn)代碼如下:
for(var i = 0; i < arr.length; i++){for(var j = i + 1; j < arr.length ; j++){//i+1表示自身和自身之前的元素都不需要比較了if(arr[i] == arr[j]){console.log(arr[i]);}cont ++;//累計(jì) } } console.log(cont);//120這樣改進(jìn)后的查重效率可以從對(duì)比次數(shù)看到,減少了一半多,也就說(shuō)明了改進(jìn)后的查重算法效率提高了一倍多。在算法中,不存在對(duì)錯(cuò)的概念,而是在保證實(shí)現(xiàn)功能的最優(yōu)方案是什么。這些最優(yōu)方案就是我們需要的算法,這些算法可以提高用戶的體驗(yàn),減少硬件資源的消耗。
用這樣的思路我們來(lái)實(shí)現(xiàn)以下數(shù)組去重算法:(這段代碼折疊,大家可以先嘗試自己寫)
function unique(arr){var obj = {};var result = [];for(var i in arr){if(!obj[arr[i]]){obj[arr[i]] = true;result.push(arr[i]);}}return result; } 數(shù)組去重算法入門之經(jīng)典的排序算法詳解
- 冒泡排序
- 選擇排序
這里暫時(shí)介紹兩種排序算法,就這兩種排序算法介紹一些關(guān)于排序的應(yīng)用場(chǎng)景解析,在前面的查重和去重算法中我們主要考慮到了效率。接著我們用這兩個(gè)排序算法來(lái)將算法的解決特定問(wèn)題引述出來(lái),這兩個(gè)算法并不能全面說(shuō)明什么是特定的問(wèn)題,它們僅僅只能告訴我們不同的算法存在其優(yōu)點(diǎn)和缺點(diǎn),適應(yīng)的場(chǎng)景也就會(huì)隨之發(fā)生變化,而這些場(chǎng)景往往來(lái)自不同的業(yè)務(wù)和功能的需求,需求來(lái)源不同,但可以根據(jù)其不同特性歸類從而選擇不同的算法,這就是算法的通用性。
1.冒泡排序(升序):
for(var j = 0; j < arr.length - 1; j++){for(var i = 0; i < arr.length - j - 1; i++){if(arr[i] > arr[i + 1]){var temp = arr[i];arr[i] = arr[i + 1];arr[i + 1] = temp;}} }首先我們就這這個(gè)升序的冒泡排序算法做一個(gè)圖解,來(lái)理解冒泡排序的邏輯及其原理:
假設(shè)有數(shù)組:var arr = [5,3,7,2,8,6,1,9,4];
當(dāng)外層循環(huán)第一次時(shí):j == 0, i == 0。
通過(guò)一次外層循環(huán),圖解內(nèi)部完全循環(huán),可以看到冒泡循環(huán)就是通過(guò)兩個(gè)相鄰元素兩兩比較,升序就是將大值交換到后面的邏輯,每一次外層循環(huán)都可以獲得對(duì)應(yīng)循環(huán)終點(diǎn)的最大值。既然是兩兩比較,那么最一個(gè)單獨(dú)的元素就不需要在循環(huán)比較了,所以外層循環(huán)也可以減去一次。
2.選擇排序(升序):
for(var j = 0; j < arr.length - 1; j ++){var max = 0;for(var i = 0; i < arr.length - j - 1; i++){if (arr[i + 1] > arr[max]) {max = i + 1;}}var temp = arr[arr.length - j -1];arr[arr.length - j - 1] = arr[max];arr[max] = temp; }選擇排序的邏輯就是外層負(fù)責(zé)交換,內(nèi)層負(fù)責(zé)找到對(duì)應(yīng)一次外層循環(huán)終點(diǎn)內(nèi)的最大值的索引,然后在一次外層循環(huán)結(jié)束時(shí),將最大值與該次循環(huán)終點(diǎn)的元素進(jìn)行交換位置。下面提供選擇排序的圖解:
假設(shè)有數(shù)組:var arr = [5,3,7,2,8,6,1,9,4];
-
第一輪外層循環(huán)
i? [i+1]>[max]??max
0 3>5 =>false ? 0 ?
1 7>5 =>true??? 2? ?
2 2>7 =>false? 2 ?
3 8>7 =>true??? 4? ?
4 6>8 =>false? 4? ?
5 1>8 =>false? 4? ?
6 9>8 =>true??? 7? ?
7 4>9 =>false ? 7? ?
max=7;終點(diǎn)=8; ?
-
第二輪外層循環(huán)
i??[i+1]>[max]??max
0 3>5 =>false?? 0??
1? 7>5 =>true??? 2 ??
2 2>7 =>false? 2 ?
3 8>7 =>true??? 4? ?
4 6>8 =>false?? 4? ?
5 1>8 =>false?? 4? ?
6 4>8 =>false?? 4? ?
max=4;終點(diǎn)=7; ?
-
第三輪外層循環(huán)
i??[i+1]>[max]??max
0 3>5 =>false?? 0??
1? 7>5 =>true??? 2 ??
2 2>7 =>false? 2 ?
3 4>7 =>false ?? 2 ?
4 6>7 =>false?? 2 ?
5 1>7 =>false?? 2 ?
max=2;終點(diǎn)=6; ?
-
第四輪外層循環(huán)
i??[i+1]>[max]??max
0 3>5 =>false?? 0??
1? 1>5 =>false ? 0 ?
2? 2>5 =>false? 0?
3?? 4>5 =>false ? 0? ?
4?? 6>5 =>true ?? 5?
max=5;終點(diǎn)=5; ?
-
第五輪外層循環(huán)
i??[i+1]>[max]??max
0 3>5 =>false?? 0??
1 1>5 =>false ? 0 ?
2 2>5 =>false ? 0?
3 4>5 =>false ?? 0 ?
max=0;終點(diǎn)=4; ?
-
第六輪外層循環(huán)
i??[i+1]>[max]??max
0 3>4 =>false?? 0??
1? 1>4 =>false ? 0 ?
2 2>4 =>false?? 0
max=0;終點(diǎn)=3; ?
-
第七輪外層循環(huán)
i??[i+1]>[max]??max
0? 3>2 =>true?? 1 ?
1? 1>3 =>false ? 1 ?
max=1;終點(diǎn)=2; ?
-
第八輪外層循環(huán)
i??[i+1]>[max]??max
0 1>2 =>false?? 0?
max=0;終點(diǎn)=1; ?
?
?
?
?
?
?
?
?
?
?
?
?
通過(guò)上圖將選擇排序的處理邏輯可視化展示后,可以看到交換次數(shù)明顯少于冒泡排序,但是借助了一個(gè)最大值索引變量來(lái)完成,這個(gè)變量會(huì)在每次外層循環(huán)時(shí)被創(chuàng)建,從這個(gè)角度來(lái)說(shuō)對(duì)于空間的需求比冒泡排序要大。從效率的角度來(lái)講選擇排序的空間效率是肯定弱于冒泡排序,但是時(shí)間效率會(huì)如何呢?這個(gè)問(wèn)題需要考慮更多的因素才能得到結(jié)果,由于這篇博客是基于入門級(jí)別的角度來(lái)闡述,所以暫時(shí)不探討太深入的問(wèn)題。
通過(guò)兩個(gè)排序算法我們可以了解到解決同一個(gè)問(wèn)題有多種方案,但是不同方案會(huì)有不同的優(yōu)勢(shì)和劣勢(shì),怎么在實(shí)際問(wèn)題中應(yīng)用這兩個(gè)算法,需要對(duì)它們的優(yōu)勢(shì)和劣勢(shì)進(jìn)行深入的分析,這不在入門的范圍內(nèi),后期會(huì)有博客更新算法知識(shí)點(diǎn)的深入理解部分。這篇博客旨在介紹算法是什么?我們?nèi)绾螌?duì)具體問(wèn)題進(jìn)行分析及編寫算法,所以上面的兩個(gè)排序算法還并不是我們能拿來(lái)解決具體問(wèn)題的工具,我們還需要對(duì)其進(jìn)一步邏輯分析和封裝,修改成可以在需要是隨時(shí)使用的函數(shù)。
- 排序算法需要做的核心工作是什么?
- 排序算法都有什么共同的特點(diǎn)?
?這兩個(gè)問(wèn)題其實(shí)是一個(gè)問(wèn)題,排序算法的核心工作就是【比較+交換】,這也是排序算法的共同特點(diǎn),所以根據(jù)這個(gè)核心工作原理,上面兩個(gè)排序算法可以封裝成以下具體方法:
//比較 function compare(a,b){if (a > b) {return true;}else{return false;} } //交換 function exchange(arr,m,n){var temp = arr[m];arr[m] = arr[n];arr[n] = temp; } //封裝冒泡排序 function bubbleSort(arr){for(var j = 0; j < arr.length - 1; j++){for(var i = 0; i < arr.length - j - 1 ; i++){if(compare(arr[i] , arr[i + 1])){exchange(arr,i,i+1)}}} } //封裝選擇排序 function selectionSort(arr){for(var j = 0; j < arr.length - 1; j ++){var max = 0;for(var i = 0; i < arr.length - j - 1; i++){if(compare(arr[i +1] , arr[max])){max = i + 1;}}exchange(arr,arr.length - j -1,max);} }了解到這里,我們應(yīng)該可以大概的理解算法的定義了:算法是指解題方案的準(zhǔn)確而完整的描述,是一系列解決問(wèn)題的清晰指定,算法代表著用系統(tǒng)的方法描述解決問(wèn)題的策略機(jī)制。對(duì)于同一個(gè)問(wèn)題我們又會(huì)有不同的策略機(jī)制,就拿排序算法來(lái)說(shuō),我們分析的就有兩種了,但是并不止這兩種,常見的排序算法還有快速排序、直接插入排序、希爾排序、堆排序、歸并排序、基數(shù)排序。不同的排序算法有不同的應(yīng)用場(chǎng)景,有時(shí)間再來(lái)更新深入分析算法的內(nèi)容了,今天是大年初四,在這里祝福大家豬年好運(yùn),身體健康,豬定幸福!
想深入了解算法的話可以先參考這兩個(gè)博客:
排序算法的穩(wěn)定性
算法的復(fù)雜度
轉(zhuǎn)載于:https://www.cnblogs.com/ZheOneAndOnly/p/10355397.html
總結(jié)
以上是生活随笔為你收集整理的前端工程师算法(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python多线程的两种写法
- 下一篇: Kubernetes 选择 IPVS