freecodecamp高級(jí)算法題(個(gè)人解法)

Validate US Telephone Numbers

檢查是否是美國(guó)電話號(hào)碼。其中有很多變體寫(xiě)法,也要求返回正確。

functiontelephoneCheck(str){vara = str.match(/[0-9]/g).length;varb = str.match(/^(?:(?:\(\d{3}\)|\d{3})[\s|-]?\d{3}[\s|-]?\d{4}$)/);varc = str.match(/(?:\(\d{3}\)|\d{3})[\s|-]?\d{3}[\s|-]?\d{4}$/);vard = str.match(/^1[^0-9]/);if(a ===10&& b !==null) {returntrue;? ? }elseif(a ===11&& c !==null&& d !==null) {returntrue;? ? }returnfalse;}telephoneCheck("2 757 622-7382");

本來(lái)嘗試使用一個(gè)正則直接得出結(jié)果,很可惜受限于水平原因,最后放棄了嘗試。

最后的代碼里面,通過(guò)a檢查傳入字符串中有多少個(gè)數(shù)字,在后面的if條件判斷中,分兩種情況(是否帶有國(guó)家代碼)來(lái)判斷。

值b用來(lái)匹配不帶國(guó)家代碼的電話號(hào)碼,前面的部分較后面來(lái)說(shuō)比較復(fù)雜。需要匹配三個(gè)數(shù)字及三個(gè)數(shù)字加括號(hào)這兩種情況,但一邊單括號(hào)應(yīng)當(dāng)不能通過(guò)驗(yàn)證。(?:(\d{3})|\d{3})這里,使用(?:)非捕獲括號(hào),里面用 | 做了一個(gè)條件判斷,從而達(dá)到匹配三個(gè)數(shù)字或三個(gè)數(shù)字加括號(hào)這兩種情況。前面的^用來(lái)防止匹配到帶國(guó)家代碼的電話(如果把b匹配放入if內(nèi),可以去掉這個(gè)^,因?yàn)橐呀?jīng)通過(guò)a的數(shù)值判斷了是否帶國(guó)家代碼)。

值c和值b沒(méi)什么區(qū)別。

值d用來(lái)匹配國(guó)家代碼開(kāi)頭部分(應(yīng)該可以和c合并,當(dāng)時(shí)只為通關(guān)也就沒(méi)改了)。

Symmetric Difference

接受兩個(gè)或者多個(gè)數(shù)組。如果是兩個(gè)數(shù)組,互相判定差集,把結(jié)果作為一個(gè)集合輸出。如果是多個(gè)數(shù)組,用上一次的結(jié)果作為其中一個(gè)數(shù)組,和下一個(gè)做相同的操作(就是reduce啦)。

functionsym1(a, b){varc = [];for(variina) {if(b.indexOf(a[i]) ===-1) {? ? ? ? ? ? c.push(a[i]);? ? ? ? }? ? }for(varyinb) {if(a.indexOf(b[y]) ===-1) {? ? ? ? ? ? c.push(b[y]);? ? ? ? }? ? }returnc;}functionsym(args){vard = [];for(variinarguments) {? ? ? ? d.push(arguments[i]);? ? }vare = d.reduce(sym1);varf = [e[0]];for(vari =1; i < e.length; i++) {if(e[i] !== e[i -1]) {? ? ? ? ? ? f.push(e[i]);? ? ? ? }? ? }returnf;}sym([1,2,3], [5,2,1,4]);

先寫(xiě)了一個(gè)reduce用的函數(shù)smy1。用indexOf判斷元素是否在集合中,如果不存在就放入準(zhǔn)備好的結(jié)果容器c中。

接下來(lái)在主函數(shù)中用for循環(huán)arguments取出輸入的所有數(shù)組,再使用reduce依次對(duì)等差分。注意這時(shí)如果輸入的數(shù)組中有多個(gè)重復(fù)的值,而這個(gè)值滿足差分的要求,結(jié)果的數(shù)組中也會(huì)出現(xiàn)很多個(gè)相同的值。但是網(wǎng)站左側(cè)給出的例子要求我們不能出現(xiàn)重復(fù),因此用一個(gè)for循環(huán)進(jìn)行去重。

Exact Change

寫(xiě)一個(gè)收銀程序。

function checkCashRegister(price, cash, cid) {? ? var change;? ? var a =0;? ? var b = [];? ? var e = cash - price;? ? var d = [0.01,0.05,0.10,0.25,1,5,10,20,100];? ? for (var i in cid) {? ? ? ? a += cid[i][1];? ? }? ? if ((cash - price) > a) {? ? ? ? return 'Insufficient Funds';? ? } else if ((cash - price) === a) {? ? ? ? return 'Closed';? ? }? ? for (var i = d.length -1; i >=0; i--) {? ? ? ? if (i ===0&& e <= cid[i][1]) {? ? ? ? ? ? b.push([cid[i][0], Math.round(e *100) /100]);? ? ? ? ? ? e =0;? ? ? ? } else if (e >= d[i] && e <= cid[i][1] && cid[i][1] >0) {? ? ? ? ? ? b.push([cid[i][0], Math.floor(e / d[i]) * d[i]]);? ? ? ? ? ? e = e - Math.floor(e / d[i]) * d[i];? ? ? ? } else if (e >= d[i] && e >= cid[i][1] && cid[i][1] >0) {? ? ? ? ? ? b.push(cid[i]);? ? ? ? ? ? e = e - cid[i][1];? ? ? ? }? ? ? ? if (e ===0) {? ? ? ? ? ? break;? ? ? ? }? ? }? ? if (e !==0) {? ? ? ? return 'Insufficient Funds';? ? }? ? return b;}sym([1,2,3], [5,2,1,4]);

第一個(gè)for循環(huán)不用看,出現(xiàn)的原因只是代碼通過(guò)了就沒(méi)改。

第二個(gè)for循環(huán)是核心代碼。我的思路是用for循環(huán)對(duì)大面額到小面額依次進(jìn)行判斷。每次會(huì)操作兩個(gè)變量,一個(gè)是結(jié)果容器b(push進(jìn)一個(gè)列表,包含面額,和剩余金額),一個(gè)是e(初始量是待找金額,每次循環(huán)如果面額和余額滿足要求,從e中扣除一定的錢(qián))。如果循環(huán)中出現(xiàn)e=0的情況,用break語(yǔ)句跳出,因?yàn)榇藭r(shí)找零已經(jīng)完成。如果直到循環(huán)結(jié)束,e仍有剩余,說(shuō)明錢(qián)找不開(kāi)。

感覺(jué)代碼還是亂,有修改的余地。

Inventory Update

依照一個(gè)存著新進(jìn)貨物的二維數(shù)組,更新存著現(xiàn)有庫(kù)存(在 arr1 中)的二維數(shù)組. 如果貨物已存在則更新數(shù)量 . 如果沒(méi)有對(duì)應(yīng)貨物則把其加入到數(shù)組中,更新最新的數(shù)量. 返回當(dāng)前的庫(kù)存數(shù)組,且按貨物名稱的字母順序排列。

functionupdateInventory(arr1, arr2){vara = [];for(variinarr1) {? ? ? ? a.push(arr1[i][1]);? ? }for(variinarr2) {if(a.indexOf(arr2[i][1]) !==-1) {? ? ? ? ? ? arr1[a.indexOf(arr2[i][1])][0] += arr2[i][0];? ? ? ? }else{? ? ? ? ? ? arr1.push(arr2[i]);? ? ? ? }? ? }? ? arr1 = arr1.sort(function(a, b){returna[1].charCodeAt(0) - b[1].charCodeAt(0);? ? });returnarr1;}

用for循環(huán)遍歷進(jìn)貨,用indexOf判斷進(jìn)貨中貨物名稱是否已經(jīng)在庫(kù)存中存在,如果存在就更新貨物數(shù)量,不存在則直接把這個(gè)數(shù)組加入庫(kù)存。

按貨物名稱排序我直接用在sort內(nèi)寫(xiě)了一個(gè)匿名函數(shù),通過(guò)比較字母的ASCII大小排序。

No repeats please

把一個(gè)字符串中的字符重新排列生成新的字符串,返回新生成的字符串里沒(méi)有連續(xù)重復(fù)字符的字符串個(gè)數(shù).連續(xù)重復(fù)只以單個(gè)字符為準(zhǔn)

例如, aab 應(yīng)該返回 2 因?yàn)樗偣灿?中排列 (aab, aab, aba, aba, baa, baa), 但是只有兩個(gè) (aba and aba)沒(méi)有連續(xù)重復(fù)的字符 (在本例中是 a).

function perms(str) {? ? var result = [];? ? var n =0;? ? var m =str.length;? ? var perm = function(str, n, m) {if(n === m -1) {? ? ? ? ? ? result.push(str.join(''));? ? ? ? }else{for(var i = n; i < m; i++) {str[i] = [str[n],str[n] =str[i]][0];? ? ? ? ? ? ? ? perm(str, n +1, m);str[i] = [str[n],str[n] =str[i]][0];? ? ? ? ? ? }? ? ? ? }? ? };? ? perm(str, n, m);returnresult;}function permAlone(str) {? ? var regex = /(.)\1+/g;str=str.split('');? ? var b = perms(str);? ? varfilter= b.filter(function(a) {return! a.match(regex);? ? });returnfilter.length;}

一開(kāi)始當(dāng)成一個(gè)數(shù)學(xué)題來(lái)做,想了很久,發(fā)現(xiàn)其中要判斷的情況太多,寫(xiě)出代碼要很多條件判斷。最后還是用全排列做了。

我的全排列函數(shù)perms是用遞歸做的。思路是,有一個(gè)可用字符集合,取出其中一個(gè),放在首位,接著更新這個(gè)字符集(集合中去除這個(gè)放在首位的字符),接著在新字符集中取出其中一個(gè)……不斷循環(huán)直至其中只有一個(gè)字符。在寫(xiě)代碼的時(shí)候變了一下實(shí)現(xiàn)方式,變成首字符和它后面的每一個(gè)字符依次交換,第二個(gè)字符和它后面的每一個(gè)字符依次交換,直至遞歸出口(倒數(shù)第二個(gè)字符)。

注意里面的匿名函數(shù)里的閉包情況(遞歸中每一次重新調(diào)用自身,并沒(méi)有創(chuàng)建一個(gè)新的變量,它們都在操作同一個(gè)str,n,m。所以交換完了要再把str還原。遞歸出口是把此時(shí)的str組裝成一個(gè)字符串。這個(gè)操作不僅有輸出格式上的考量,還有一個(gè)原因是,既然操作的都是同一個(gè)str,那么push進(jìn)數(shù)組的當(dāng)然也是同一個(gè)str,雖然它們身處數(shù)組,但一直在隨著函數(shù)里的str的變化而變化。所以我們需要把每次遞歸出口的str順序固定下來(lái),組裝字符串相當(dāng)于創(chuàng)建了一個(gè)新的字符串對(duì)象,從而達(dá)到固定順序的作用)。

Friendly Date Ranges

functionmakeDates(str){vararr = [];? ? str = str.split(/[^\d*]/);for(vari in str) {? ? ? ? arr.push(parseInt(str[i],10));? ? }returnarr;}functionmakeFriendlyDates(arr){varmonth = ['','January','February','March','April','May','June','July','August','September','October','November','December'];vardays = [];vararray= [];for(varz =0; z <31; z++) {if(z >=10&& z <=20) {? ? ? ? ? ? days.push('th');? ? ? ? }else{if(z %10===1) {? ? ? ? ? ? ? ? days.push('st');? ? ? ? ? ? }elseif(z %10===2) {? ? ? ? ? ? ? ? days.push('nd');? ? ? ? ? ? }elseif(z %10===3) {? ? ? ? ? ? ? ? days.push('rd');? ? ? ? ? ? }else{? ? ? ? ? ? ? ? days.push('th');? ? ? ? ? ? }? ? ? ? }? ? }for(vari in arr) {array.push(makeDates(arr[i]));? ? }vara =array[1][0] -array[0][0];varb =array[1][1] -array[0][1];varc =array[1][2] -array[0][2];for(vary inarray) {array[y][0] = [array[y][2],array[y][2] =array[y][0]][0];array[y][0] = [array[y][1],array[y][1] =array[y][0]][0];? ? ? ? replace(array[y]);? ? }functionreplace(array){array[0] = month[array[0]];array[1] = String(array[1]) + days[array[1]];array[2] = String(array[2]);if(array.length ===3) {array[1] =array[1] +',';? ? ? ? }? ? }if(a *360+ b *30+ c >=360) {}elseif(a *360+ b *30+ c >30&&array[0][2] ==='2016') {array[1] =array[1].splice(0,2);array[0] =array[0].splice(0,2);? ? }elseif(a *360+ b *30+ c >30) {array[1] =array[1].splice(0,2);array[0] =array[0].splice(0,3);? ? }elseif(a *360+ b *30+ c >0) {array[1] = [array[1][1]];array[0] =array[0].splice(0,2);? ? }elseif(a ===0&& b ===0&& c ===0) {array= [array[0]];? ? }returnarray.map(function(a){returna.join(' ').replace(/,$/,'');? ? });}

把一大堆條件判斷從人類語(yǔ)言轉(zhuǎn)換成代碼。。。。。。。這就是我寫(xiě)這題的感覺(jué),也許出題人的初衷不是這個(gè)?

Make a Person

varPerson =function(name){vara = [name.split(' ')[0], name.split(' ')[1]];this.getFirstName =function(){returna[0];? ? };this.getLastName =function(){returna[1];? ? };this.getFullName =function(){returna[0] +' '+ a[1];? ? };this.setFirstName =function(b){? ? ? ? a[0] = b;? ? };this.setLastName =function(b){? ? ? ? a[1] = b;? ? };this.setFullName =function(b){? ? ? ? a[0] = b.split(' ')[0];? ? ? ? a[1] = b.split(' ')[1];? ? };};varbob =newPerson('Bob Ross');bob.getFirstName();

匿名函數(shù)function(name)在類建立時(shí)就被調(diào)用,它用來(lái)建立一個(gè)類空間,其中的內(nèi)容即是建立的類的內(nèi)容。變量a用一個(gè)數(shù)組來(lái)儲(chǔ)存和修改Firstname及Lastname(把function(name)傳遞進(jìn)類空間的name給spilt成兩塊),給屬性賦予匿名函數(shù),通過(guò)閉包操作變量a。這六個(gè)函數(shù)大同小異,精簡(jiǎn)成一個(gè)的話,會(huì)非常簡(jiǎn)潔,同時(shí)可以清晰地看到兩個(gè)要點(diǎn)。第一是通過(guò)函數(shù)建立類,第二是閉包的使用。

Map the Debris

返回一個(gè)數(shù)組,其內(nèi)容是把原數(shù)組中對(duì)應(yīng)元素的平均海拔轉(zhuǎn)換成其對(duì)應(yīng)的軌道周期.

functionorbitalPeriod(arr){varGM =398600.4418;varearthRadius =6367.4447;functionchange(avgAlt){varr = earthRadius + avgAlt;varb =Math.pow(r,3) / GM;varT =2*Math.PI *Math.pow(b,0.5);returnMath.round(T);? ? }varresult = [];for(variinarr) {vara = change(arr[i].avgAlt);vardict = {};? ? ? ? dict.name = arr[i].name;? ? ? ? dict.orbitalPeriod = a;? ? ? ? result.push(dict);? ? }returnresult;}

用代碼把數(shù)學(xué)公式算一下。外加一點(diǎn)點(diǎn)數(shù)據(jù)的取出。不太清楚為什么要放在高級(jí)算法里。

Pairwise

舉個(gè)例子:有一個(gè)能力數(shù)組[7,9,11,13,15],按照最佳組合值為20來(lái)計(jì)算,只有7+13和9+11兩種組合。而7在數(shù)組的索引為0,13在數(shù)組的索引為3,9在數(shù)組的索引為1,11在數(shù)組的索引為2。

所以我們說(shuō)函數(shù):pairwise([7,9,11,13,15],20) 的返回值應(yīng)該是0+3+1+2的和,即6。

function pairwise(arr, arg) {varcount=0;varred=[];for(vari=0;i

題目下面的提示是reduce,我的思路里面沒(méi)有用到,自己嘗試用reduce想了一下,感覺(jué)有點(diǎn)阻力。

我的思路,遍歷每個(gè)值,每次遍歷中再對(duì)目前值之后的值進(jìn)行一次遍歷。目的是每個(gè)值和它之后所有的值匹配,如果它們的和等于目標(biāo)值,則把下標(biāo)累加到變量count上。題目中還有一個(gè)值得注意的點(diǎn),就是當(dāng)兩個(gè)值匹配后,它們便不會(huì)和其他值匹配了。這里我通過(guò)一個(gè)變量red,作為一個(gè)池子,來(lái)儲(chǔ)存已經(jīng)匹配過(guò)的變量的下標(biāo)。再循環(huán)中先進(jìn)行條件判斷,若取出的值不在池中才進(jìn)行下一步匹配(使用continue來(lái)實(shí)現(xiàn),continue:跳過(guò)次循環(huán)直接執(zhí)行下一次循環(huán),也可以使用一個(gè)if,判斷條件里用&&把“求和是否滿足要求”及“下標(biāo)是否在池中”連起來(lái))。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容