轉型程序員freecodecamp高級算法題(個人解法)

剛剛開始自學,網上很多相關帖子上來直接報上兩頁菜名成箫,初一看很有武俠小說里說書人的感覺.這本書怎樣怎樣展箱,那本書如何如何(本人文筆不行,可以自行腦補網絡小說各類比武橋段中龍?zhí)装l(fā)言)蹬昌。轉了一圈下來混驰,各類電子書下了不少,收藏夾也增長了幾頁皂贩。
  真正學起來栖榨,才發(fā)現(xiàn)需要一個好的學習路徑和對應的代碼練習。其中代碼練習尤其地少明刷。有人也許會說婴栽,那么多代碼書,自己跟著敲一敲不就是練習么辈末,這還學不會愚争?刷題網站那么多,自己去刷題凹菲浮轰枝!
  我打個比方,咱們都學過數(shù)學组去。除了那種看一看教材解釋鞍陨,就能完美理解的天才;兩個普通學生添怔,一個學習完數(shù)學定義及公式后湾戳,自己出題給自己做;一個則做各類教輔習題广料,這兩種情境下,學習效率絕對是天差地別的幼驶。再者艾杏,刷題網站的題目默認刷題者對語言已經學習完畢,重點在于對計算機原理及數(shù)學的應用盅藻。
  綜上购桑,個人感覺freecodecamp對我這種半路自學的人還是有不少幫助的∈鲜纾花了一段時間勃蜘,按照它給的學習順序,從新手教程一直做到了高級算法題結束假残。在這里自己回顧一下之前自己的解法缭贡。

Validate US Telephone Numbers

檢查是否是美國電話號碼炉擅。其中有很多變體寫法,也要求返回正確阳惹。

function telephoneCheck(str) {
    var a = str.match(/[0-9]/g).length;
    var b = str.match(/^(?:(?:\(\d{3}\)|\d{3})[\s|-]?\d{3}[\s|-]?\d{4}$)/);
    var c = str.match(/(?:\(\d{3}\)|\d{3})[\s|-]?\d{3}[\s|-]?\d{4}$/);
    var d = str.match(/^1[^0-9]/);
    if (a === 10 && b !== null) {
        return true;
    } else if (a === 11 && c !== null && d !== null) {
        return true;
    }
    return false;
}
telephoneCheck("2 757 622-7382");

本來嘗試使用一個正則直接得出結果谍失,很可惜受限于水平原因,最后放棄了嘗試莹汤。
  最后的代碼里面快鱼,通過a檢查傳入字符串中有多少個數(shù)字,在后面的if條件判斷中纲岭,分兩種情況(是否帶有國家代碼)來判斷抹竹。
  值b用來匹配不帶國家代碼的電話號碼,前面的部分較后面來說比較復雜止潮。需要匹配三個數(shù)字及三個數(shù)字加括號這兩種情況窃判,但一邊單括號應當不能通過驗證。(?:(\d{3})|\d{3})這里沽翔,使用(?:)非捕獲括號兢孝,里面用 | 做了一個條件判斷,從而達到匹配三個數(shù)字或三個數(shù)字加括號這兩種情況仅偎。前面的用來防止匹配到帶國家代碼的電話(如果把b匹配放入if內跨蟹,可以去掉這個,因為已經通過a的數(shù)值判斷了是否帶國家代碼)橘沥。
  值c和值b沒什么區(qū)別窗轩。
  值d用來匹配國家代碼開頭部分(應該可以和c合并,當時只為通關也就沒改了)座咆。

Symmetric Difference

接受兩個或者多個數(shù)組痢艺。如果是兩個數(shù)組,互相判定差集介陶,把結果作為一個集合輸出堤舒。如果是多個數(shù)組,用上一次的結果作為其中一個數(shù)組哺呜,和下一個做相同的操作(就是reduce啦)舌缤。

function sym1(a, b) {
    var c = [];
    for (var i in a) {
        if (b.indexOf(a[i]) === -1) {
            c.push(a[i]);
        }
    }
    for (var y in b) {
        if (a.indexOf(b[y]) === -1) {
            c.push(b[y]);
        }
    }
    return c;
}
function sym(args) {
    var d = [];
    for (var i in arguments) {
        d.push(arguments[i]);
    }
    var e = d.reduce(sym1);
    var f = [e[0]];
    for (var i = 1; i < e.length; i++) {
        if (e[i] !== e[i - 1]) {
            f.push(e[i]);
        }
    }
    return f;
}

sym([1, 2, 3], [5, 2, 1, 4]);

先寫了一個reduce用的函數(shù)smy1。用indexOf判斷元素是否在集合中某残,如果不存在就放入準備好的結果容器c中国撵。
  接下來在主函數(shù)中用for循環(huán)arguments取出輸入的所有數(shù)組,再使用reduce依次對等差分玻墅。注意這時如果輸入的數(shù)組中有多個重復的值介牙,而這個值滿足差分的要求,結果的數(shù)組中也會出現(xiàn)很多個相同的值澳厢。但是網站左側給出的例子要求我們不能出現(xiàn)重復环础,因此用一個for循環(huán)進行去重囚似。

Exact Change

寫一個收銀程序。

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]);

第一個for循環(huán)不用看喳整,出現(xiàn)的原因只是代碼通過了就沒改谆构。
  第二個for循環(huán)是核心代碼。我的思路是用for循環(huán)對大面額到小面額依次進行判斷框都。每次會操作兩個變量搬素,一個是結果容器b(push進一個列表,包含面額魏保,和剩余金額)熬尺,一個是e(初始量是待找金額,每次循環(huán)如果面額和余額滿足要求谓罗,從e中扣除一定的錢)粱哼。如果循環(huán)中出現(xiàn)e=0的情況,用break語句跳出檩咱,因為此時找零已經完成揭措。如果直到循環(huán)結束,e仍有剩余刻蚯,說明錢找不開绊含。 
  感覺代碼還是亂炊汹,有修改的余地躬充。

Inventory Update

依照一個存著新進貨物的二維數(shù)組,更新存著現(xiàn)有庫存(在 arr1 中)的二維數(shù)組. 如果貨物已存在則更新數(shù)量 . 如果沒有對應貨物則把其加入到數(shù)組中讨便,更新最新的數(shù)量. 返回當前的庫存數(shù)組充甚,且按貨物名稱的字母順序排列。

function updateInventory(arr1, arr2) {
    var a = [];
    for (var i in arr1) {
        a.push(arr1[i][1]);
    }
    for (var i in arr2) {
        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) {
        return a[1].charCodeAt(0) - b[1].charCodeAt(0);
    });
    return arr1;
}

用for循環(huán)遍歷進貨霸褒,用indexOf判斷進貨中貨物名稱是否已經在庫存中存在伴找,如果存在就更新貨物數(shù)量,不存在則直接把這個數(shù)組加入庫存废菱。
  按貨物名稱排序我直接用在sort內寫了一個匿名函數(shù)疆瑰,通過比較字母的ASCII大小排序。

No repeats please

把一個字符串中的字符重新排列生成新的字符串昙啄,返回新生成的字符串里沒有連續(xù)重復字符的字符串個數(shù).連續(xù)重復只以單個字符為準
  例如, aab 應該返回 2 因為它總共有6中排列 (aab, aab, aba, aba, baa, baa), 但是只有兩個 (aba and aba)沒有連續(xù)重復的字符 (在本例中是 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);
    return result;
}
function permAlone(str) {
    var regex = /(.)\1+/g;
    str = str.split('');
    var b = perms(str);
    var filter = b.filter(function(a) {
        return ! a.match(regex);
    });
    return filter.length;
}

一開始當成一個數(shù)學題來做,想了很久寸五,發(fā)現(xiàn)其中要判斷的情況太多梳凛,寫出代碼要很多條件判斷。最后還是用全排列做了梳杏。
  我的全排列函數(shù)perms是用遞歸做的韧拒。思路是淹接,有一個可用字符集合,取出其中一個叛溢,放在首位塑悼,接著更新這個字符集(集合中去除這個放在首位的字符),接著在新字符集中取出其中一個……不斷循環(huán)直至其中只有一個字符楷掉。在寫代碼的時候變了一下實現(xiàn)方式厢蒜,變成首字符和它后面的每一個字符依次交換,第二個字符和它后面的每一個字符依次交換烹植,直至遞歸出口(倒數(shù)第二個字符)斑鸦。
  注意里面的匿名函數(shù)里的閉包情況(遞歸中每一次重新調用自身,并沒有創(chuàng)建一個新的變量草雕,它們都在操作同一個str巷屿,n,m墩虹。所以交換完了要再把str還原嘱巾。遞歸出口是把此時的str組裝成一個字符串。這個操作不僅有輸出格式上的考量诫钓,還有一個原因是旬昭,既然操作的都是同一個str,那么push進數(shù)組的當然也是同一個str尖坤,雖然它們身處數(shù)組稳懒,但一直在隨著函數(shù)里的str的變化而變化。所以我們需要把每次遞歸出口的str順序固定下來慢味,組裝字符串相當于創(chuàng)建了一個新的字符串對象场梆,從而達到固定順序的作用)。

Friendly Date Ranges

function makeDates(str) {
    var arr = [];
    str = str.split(/[^\d*]/);
    for (var i in str) {
        arr.push(parseInt(str[i], 10));
    }
    return arr;
}

function makeFriendlyDates(arr) {
    var month = ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
    var days = [];
    var array = [];
    for (var z = 0; z < 31; z++) {
        if (z >= 10 && z <= 20) {
            days.push('th');
        } else {
            if (z % 10 === 1) {
                days.push('st');
            } else if (z % 10 === 2) {
                days.push('nd');
            } else if (z % 10 === 3) {
                days.push('rd');
            } else {
                days.push('th');
            }
        }
    }
    for (var i in arr) {
        array.push(makeDates(arr[i]));
    }
    var a = array[1][0] - array[0][0];
    var b = array[1][1] - array[0][1];
    var c = array[1][2] - array[0][2];
    for (var y in array) {
        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]);
    }
    function replace(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) {} else if (a * 360 + b * 30 + c > 30 && array[0][2] === '2016') {
        array[1] = array[1].splice(0, 2);
        array[0] = array[0].splice(0, 2);
    } else if (a * 360 + b * 30 + c > 30) {
        array[1] = array[1].splice(0, 2);
        array[0] = array[0].splice(0, 3);
    } else if (a * 360 + b * 30 + c > 0) {
        array[1] = [array[1][1]];
        array[0] = array[0].splice(0, 2);
    } else if (a === 0 && b === 0 && c === 0) {
        array = [array[0]];
    }
    return array.map(function(a) {
        return a.join(' ').replace(/,$/, '');
    });
}

把一大堆條件判斷從人類語言轉換成代碼纯路。或油。。驰唬。顶岸。。叫编。這就是我寫這題的感覺辖佣,也許出題人的初衷不是這個?

Make a Person

var Person = function(name) {
    var a = [name.split(' ')[0], name.split(' ')[1]];
    this.getFirstName = function() {
        return a[0];
    };
    this.getLastName = function() {
        return a[1];
    };
    this.getFullName = function() {
        return a[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];
    };
};
var bob = new Person('Bob Ross');
bob.getFirstName();

匿名函數(shù)function(name)在類建立時就被調用搓逾,它用來建立一個類空間卷谈,其中的內容即是建立的類的內容。變量a用一個數(shù)組來儲存和修改Firstname及Lastname(把function(name)傳遞進類空間的name給spilt成兩塊)霞篡,給屬性賦予匿名函數(shù)世蔗,通過閉包操作變量a端逼。這六個函數(shù)大同小異,精簡成一個的話污淋,會非常簡潔顶滩,同時可以清晰地看到兩個要點。第一是通過函數(shù)建立類寸爆,第二是閉包的使用礁鲁。

Map the Debris

返回一個數(shù)組,其內容是把原數(shù)組中對應元素的平均海拔轉換成其對應的軌道周期.

function orbitalPeriod(arr) {
    var GM = 398600.4418;
    var earthRadius = 6367.4447;
    function change(avgAlt) {
        var r = earthRadius + avgAlt;
        var b = Math.pow(r, 3) / GM;
        var T = 2 * Math.PI * Math.pow(b, 0.5);
        return Math.round(T);
    }
    var result = [];
    for (var i in arr) {
        var a = change(arr[i].avgAlt);
        var dict = {};
        dict.name = arr[i].name;
        dict.orbitalPeriod = a;
        result.push(dict);
    }
    return result;
}

用代碼把數(shù)學公式算一下而昨。外加一點點數(shù)據(jù)的取出救氯。不太清楚為什么要放在高級算法里。

Pairwise

舉個例子:有一個能力數(shù)組[7,9,11,13,15]歌憨,按照最佳組合值為20來計算着憨,只有7+13和9+11兩種組合。而7在數(shù)組的索引為0务嫡,13在數(shù)組的索引為3甲抖,9在數(shù)組的索引為1,11在數(shù)組的索引為2心铃。
所以我們說函數(shù):pairwise([7,9,11,13,15],20) 的返回值應該是0+3+1+2的和准谚,即6。

function pairwise(arr, arg) {
  var count=0;
  var red=[];
  for(var i=0;i<arr.length;i++){
    for(var y=i+1;y<arr.length;y++){
      if(red.indexOf(i)!==-1||red.indexOf(y)!==-1){
        continue;
      }
      else if(arr[i]+arr[y]===arg){
        count+=i;
        count+=y;
        red.push(i);
        red.push(y);
      }
    }
  }
  return count;
}

題目下面的提示是reduce去扣,我的思路里面沒有用到柱衔,自己嘗試用reduce想了一下,感覺有點阻力愉棱。
  我的思路唆铐,遍歷每個值,每次遍歷中再對目前值之后的值進行一次遍歷奔滑。目的是每個值和它之后所有的值匹配艾岂,如果它們的和等于目標值,則把下標累加到變量count上朋其。題目中還有一個值得注意的點王浴,就是當兩個值匹配后,它們便不會和其他值匹配了梅猿。這里我通過一個變量red氓辣,作為一個池子,來儲存已經匹配過的變量的下標袱蚓。再循環(huán)中先進行條件判斷筛婉,若取出的值不在池中才進行下一步匹配(使用continue來實現(xiàn),continue:跳過次循環(huán)直接執(zhí)行下一次循環(huán),也可以使用一個if爽撒,判斷條件里用&&把“求和是否滿足要求”及“下標是否在池中”連起來)。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末响蓉,一起剝皮案震驚了整個濱河市硕勿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌枫甲,老刑警劉巖源武,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異想幻,居然都是意外死亡粱栖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門脏毯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來闹究,“玉大人,你說我怎么就攤上這事食店≡伲” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵吉嫩,是天一觀的道長价认。 經常有香客問我,道長自娩,這世上最難降的妖魔是什么用踩? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮忙迁,結果婚禮上脐彩,老公的妹妹穿的比我還像新娘。我一直安慰自己动漾,他們只是感情好丁屎,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著旱眯,像睡著了一般晨川。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上删豺,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天共虑,我揣著相機與錄音,去河邊找鬼呀页。 笑死妈拌,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播尘分,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼猜惋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了培愁?” 一聲冷哼從身側響起著摔,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎定续,沒想到半個月后谍咆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡私股,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年摹察,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倡鲸。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡供嚎,死狀恐怖,靈堂內的尸體忽然破棺而出旦签,到底是詐尸還是另有隱情查坪,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布宁炫,位于F島的核電站偿曙,受9級特大地震影響,放射性物質發(fā)生泄漏羔巢。R本人自食惡果不足惜望忆,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望竿秆。 院中可真熱鬧启摄,春花似錦、人聲如沸幽钢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匪燕。三九已至蕾羊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間帽驯,已是汗流浹背龟再。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留尼变,地道東北人利凑。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親哀澈。 傳聞我的和親對象是個殘疾皇子牌借,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內容