Freecodecamp 刷題記錄——前端高級算法

Validate US Telephone Numbers
如果傳入字符串是一個有效的美國電話號碼,則返回 true.

用戶可以在表單中填入一個任意有效美國電話號碼. 下面是一些有效號碼的例子(還有下面測試時用到的一些變體寫法):

555-555-5555
(555)555-5555
(555) 555-5555
555 555 5555
5555555555
1 555 555 5555
在本節(jié)中你會看見如 800-692-7753 or 8oo-six427676;laskdjf這樣的字符串. 你的任務(wù)就是驗證前面給出的字符串是否是有效的美國電話號碼. 區(qū)號是必須有的. 如果字符串中給出了國家代碼, 你必須驗證其是 1. 如果號碼有效就返回 true ; 否則返回 false.

function telephoneCheck(str) {
  // 祝你好運
    var reg = new RegExp(/^(1\s?)?((\(\d{3}\))|\d{3})[\s-]?\d{3}[\s-]?\d{4}$/);
    if (str.search(reg)>=0){
        return true;
    }

    return false;
}

str = telephoneCheck("1(555)555-5555");

console.log(str);

Symmetric Difference

創(chuàng)建一個函數(shù),接受兩個或多個數(shù)組,返回所給數(shù)組的 對等差分(symmetric difference) (△ or ⊕)數(shù)組.

給出兩個集合 (如集合 A = {1, 2, 3} 和集合 B = {2, 3, 4}), 而數(shù)學(xué)術(shù)語 "對等差分" 的集合就是指由所有只在兩個集合其中之一的元素組成的集合(A △ B = C = {1, 4}). 對于傳入的額外集合 (如 D = {2, 3}), 你應(yīng)該安裝前面原則求前兩個集合的結(jié)果與新集合的對等差分集合 (C △ D = {1, 4} △ {2, 3} = {1, 2, 3, 4}).

function sym() {
    if (arguments.length === 2){
        var arr1 = arguments[0];
        var arr2 = arguments[1];

        var tempArr = [];
        return arr1.filter(function(item){
            if (Array.from(arr2).indexOf(item) >= 0){
                return false;
            }
            return true;
        }).concat(arr2.filter(function(item){
            if (Array.from(arr1).indexOf(item) >= 0){
                return false;
            }
            return true;
        })).filter(function(item){ //去重
            if (tempArr.indexOf(item) >= 0){
                return false;
            }
            else {
                tempArr.push(item);
                return true;
            }
        });

    }
    else if(arguments.length > 2){
        var newArgs = [];
        var oldArgs = arguments;
        newArgs.push(sym(arguments[0], arguments[1]));
        for (var i=2; i<oldArgs.length; i++){
            newArgs.push(oldArgs[i]);
        }
        return sym.apply(this, newArgs);  //將數(shù)組作為參數(shù)傳遞,需要用apply,而不能直接apply(newArgs),因為參數(shù)并不是數(shù)組
    }
}

str = sym([3, 3, 3, 2, 5], [2, 1, 5, 7], [3, 4, 6, 6], [1, 2, 3]);

console.log(str);

tip1:sym.apply(this, newArgs); //將數(shù)組作為參數(shù)傳遞,需要用apply,而不能直接apply(newArgs),因為參數(shù)并不是數(shù)組;

tip2:注意需要對數(shù)組去重。

Exact Change
設(shè)計一個收銀程序 checkCashRegister() ,其把購買價格(price)作為第一個參數(shù) , 付款金額 (cash)作為第二個參數(shù), 和收銀機中零錢 (cid) 作為第三個參數(shù).

cid 是一個二維數(shù)組,存著當(dāng)前可用的找零.

當(dāng)收銀機中的錢不夠找零時返回字符串 "Insufficient Funds". 如果正好則返回字符串 "Closed".

否則, 返回應(yīng)找回的零錢列表,且由大到小存在二維數(shù)組中.

function checkCashRegister(price, cash, cid) {
    var change = [];
    //都換成整數(shù),防止浮點數(shù)陷阱。
    var VALUE = [1, 5, 10, 50, 100, 500, 1000, 2000, 10000];
    var money = (cash - price) * 100;
    cid = cid.map(function(item){
        item[1] *= 100;
        return item;
    });

    var i = 8;
    while (money > 0){
        if (i<0){
            return "Insufficient Funds";
        }

        var sum = 0;
        while (money>=VALUE[i] && cid[i][1]>0){
            money -= VALUE[i];
            cid[i][1] -= VALUE[i];
            sum += VALUE[i];
        }

        if (sum>0){
            //直接temp=cid的話,修改temp會影響cid的值,影響后面零錢是否用光的判斷
            var temp = cid.slice(); // this is how to make a copy 
            temp[1] = sum / 100;
            change.push(temp);
        }

        i--;
    }

    //零錢是否用光
    for (i=0; i<9; i++){
        if (cid[i][1]>0){
            return change;
        }
    }

    return "Closed";
}

str = checkCashRegister(19.50, 20.00, [["PENNY", 0.50], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]); 
console.log(str);

tips1:數(shù)組是指針!賦值給其它數(shù)組后,是把指針傳遞了過去,新數(shù)組改變會影響原數(shù)組?。?!

            console.log('before:' + cid[i]);
            var temp = cid;
            temp[i][1] = sum / 100;
            console.log('after:' + cid[i]);

打印結(jié)果:

before:PENNY,0
freecodecamp.js:28 after:PENNY,0.5

參考:javascript中把一個數(shù)組的內(nèi)容全部賦值給另外一個數(shù)組 - ..._博客園

Inventory Update

function updateInventory(arr1, arr2) {
    for (var j=0; j<arr2.length; j++){

        var i = 0;
        //在有序表中尋找位置
        while (i<arr1.length && arr2[j][1]>arr1[i][1]){
            i++;
        }
        console.log(i);
        if (i===arr1.length){
            arr1.push(arr2[j]);
        }
        else{
            //如果存在
            if (arr1[i][1] === arr2[j][1]){
                arr1[i][0] += arr2[j][0];
            }
            //如果未存在
            else{
                var tempArr = arr1.slice(0, i);
                tempArr.push(arr2[j]);
                arr1 = tempArr.concat(arr1.slice(i));
            }

        }

    }
    return arr1;
}

var curInv = [
    [21, "Bowling Ball"],
    [2, "Dirty Sock"],
    [1, "Hair Pin"],
    [5, "Microphone"]
];
var newInv = [
    [2, "Hair Pin"],
    [3, "Half-Eaten Apple"],
    [67, "Bowling Ball"],
    [7, "Toothpaste"]
];

str = updateInventory(curInv, newInv);

console.log(str);


tips1:
原先寫的如下代碼:

for (var j=0; j<arr2.length; j++){

        var i = 0;
        //在有序表中尋找位置
        while (arr2[j][1][0] > arr1[i][1][0]){
            i++;
        }
        ……
}

報錯:
freecodecamp.js:6 Uncaught TypeError: Cannot read property '1' of undefined

一開始以為是不能把arr2視為多維數(shù)組,對其直接取下標。而結(jié)果是,直接把參數(shù)視為多維數(shù)組沒毛病,錯誤是沒限制i的范圍,我越界了?。。?/p>

tips2:
字符串可以直接比較大小,會根據(jù)第一個不同的字符的ascii值碼進行比較,當(dāng)數(shù)字(number)與字符串(string)進行比較大小時,會強制的將數(shù)字(number)轉(zhuǎn)換成字符串(string)然后再進行比較。
例如:

console.log('13'>'3'); // 輸出:false,因為第一位'1'<'3'

No repeats please

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

例如, aab 應(yīng)該返回 2 因為它總共有6中排列 (aab, aab, aba, aba, baa, baa), 但是只有兩個 (aba and aba)沒有連續(xù)重復(fù)的字符 (在本例中是 a).

function swap(array, i, j){
    if (i!=j){
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}


function permAlone(str){
    var count = 0;

    function allSort(array, start, end) {
        if (start < end - 1){
            for (var i=start; i<end; i++){
                swap(array, start, i);
                allSort(array, start+1, end);
                swap(array, start, i);
            }
        }
        //得到一種全排列
        else{
            //判斷是否有連續(xù)重復(fù)字符
            //如果有,返回,不計數(shù)。
            for (var j=0; j < array.length - 1; j++){
                if (array[j]===array[j+1]){
                    break;
                }
            }
            if (array[j]!==array[j+1]){
                count++;
                console.log(array);
            }
        }
        return count;
    }

    //使用閉包,以便使allSort函數(shù)能直接修改count的值;
    //將字符串轉(zhuǎn)換為數(shù)組,否則string類型是無法修改的,函數(shù)只能傳遞形參,
    //而數(shù)組作為對象則傳遞的是地址。
    allSort(str.split(''), 0, str.length);

    return count;
}

console.log(permAlone('aab'));

感覺是前端算法中最難的一道題了,用到遞歸的思路。

Friendly Date Ranges
讓日期區(qū)間更友好!

把常見的日期格式如:YYYY-MM-DD 轉(zhuǎn)換成一種更易讀的格式。

易讀格式應(yīng)該是用月份名稱代替月份數(shù)字,用序數(shù)詞代替數(shù)字來表示天 (1st 代替 1).

記住不要顯示那些可以被推測出來的信息: 如果一個日期區(qū)間里結(jié)束日期與開始日期相差小于一年,則結(jié)束日期就不用寫年份了;在這種情況下,如果月份開始和結(jié)束日期如果在同一個月,則結(jié)束日期月份也不用寫了。

另外, 如果開始日期年份是當(dāng)前年份,且結(jié)束日期與開始日期小于一年,則開始日期的年份也不用寫。

例如:

包含當(dāng)前年份和相同月份的時候,makeFriendlyDates(["2017-01-02", "2017-01-05"]) 應(yīng)該返回 ["January 2nd","5th"]

不包含當(dāng)前年份,makeFriendlyDates(["2003-08-15", "2009-09-21"]) 應(yīng)該返回 ["August 15th, 2003", "September 21st, 2009"]。

請考慮清楚所有可能出現(xiàn)的情況,包括傳入的日期區(qū)間是否合理。對于不合理的日期區(qū)間,直接返回 undefined 即可

function dayAppendix(day){
    var str;
    switch (day){
    case 1: 
    case 21:
    case 31: str = "st";break;
    case 2:
    case 22: str = "nd";break;
    case 3:
    case 23: str = "rd";break;
    default: str = "th";
    }
    return str; 
}

function makeFriendlyDates(arr) {
    var d1 = arr[0].split('-').map(function(item){
        return parseInt(item);
    });
    var d2 = arr[1].split('-').map(function(item){
        return parseInt(item);
    });

    if ((d1[0]>d2[0]) || 
        (d1[0]===d2[0] && d1[1]>d2[1]) || 
        (d1[0]===d2[0] && d1[1]===d2[1] && d1[2]>d2[2])){
        return undefined;
    }

    var Month = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    var retArr = [];

    var str1 = Month[d1[1]-1] + " " + d1[2];
    var str2 = "";

    str1 += dayAppendix(d1[2]);

    var withinAYear = false;

    var deltaY = d2[0] - d1[0];
    var deltaM = d2[1] - d1[1];
    var deltaD = d2[2] - d1[2];

    if ((deltaY===0)||
        (deltaY===1 && deltaM<0)||
        (deltaY===1 && deltaM===0 && deltaD<0)){
        withinAYear = true;
    }

    var curYear = 2017;
    if (d1[0]!==curYear || !withinAYear){
        str1 = str1 + ', ' + d1[0];
    }
    retArr.push(str1);

    if (deltaY===0 && deltaM===0 && deltaD===0){
        return retArr;
    }

    if (d1[0]!==d2[0] || d1[1]!==d2[1] || !withinAYear){
        str2 += Month[d2[1]-1] + ' ';
    }
    str2 += d2[2];

    str2 += dayAppendix(d2[2]);


    if (!withinAYear){
        str2 = str2 + ', ' + d2[0];
    }

    retArr.push(str2);

    return retArr;

}


str =makeFriendlyDates(["2010-10-23", "2011-10-22"]);


console.log(str);

tips1:英文日期簡寫是根據(jù)詞尾判別的,即個位是1就是st,個位是2就是nd,個位是3就是rd,其他個位就是th,但11,12,13是例外,都用th。(根據(jù)讀音,eleven總不能加st吧)
tips2:將多個條件寫下來,驗算邏輯,比較容易捋清楚。
tips3:“開始和結(jié)束日期如果在同一個月”指的是同一年&&同一月。

Make a Person

基于原型的語言(如 JavaScript)并不存在這種區(qū)別:它只有對象?;谠偷恼Z言具有所謂原型對象的概念。原型對象可以作為一個模板,新對象可以從中獲得原始的屬性。任何對象都可以指定其自身的屬性,既可以是創(chuàng)建時也可以在運行時創(chuàng)建。而且,任何對象都可以作為另一個對象的原型,從而允許后者共享前者的屬性。

JavaScript構(gòu)造函數(shù)及原型對象 - 王浴昊 - CSDN博客

var Person = function(firstAndLast) {
    var arr = firstAndLast.split(' ');
    var firstName = arr[0];
    var lastName = arr[1];

    this.getFirstName = function(){
        return firstName;
    };
    this.getLastName = function(){
        return lastName;
    };
    this.getFullName = function(){
        return firstName + ' ' + lastName;
    };
    this.setFirstName = function(first){
        firstName = first;
    };
    this.setLastName = function(last){
        lastName = last;
    };
    this.setFullName = function(fullName){
        firstAndLast = fullName;
        var tempArr = fullName.split(' ');
        firstName = tempArr[0];
        lastName = tempArr[1];
    };
};

var bob = new Person('Bob Ross');
console.log(bob);

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

原數(shù)組中會包含格式化的對象內(nèi)容,像這樣 {name: 'name', avgAlt: avgAlt}.

至于軌道周期怎么求,戳這里 on wikipedia (不想看英文的話可以自行搜索以軌道高度計算軌道周期的公式).

求得的值應(yīng)該是一個與其最接近的整數(shù),軌道是以地球為基準的.

地球半徑是 6367.4447 kilometers, 地球的GM值是 398600.4418, 圓周率為Math.PI

function orbitalPeriod(arr) {
    var GM = 398600.4418;
    var earthRadius = 6367.4447;
    return arr.map(function(obj){
        var R = (obj.avgAlt + earthRadius);

        var retObj = {};
        retObj.name = obj.name;
        retObj.orbitalPeriod = Math.round(2 * Math.PI * R * Math.pow(R/GM, 0.5));

        return retObj;
    });
}

str = orbitalPeriod([{name : "sputnik", avgAlt : 35873.5553}]);

console.log(str);

Pairwise
找到你的另一半

都說優(yōu)秀的程序員擅長面向?qū)ο缶幊?,但卻經(jīng)常找不到另一半,這是為什么呢?因為你總是把自己局限成為一個程序員,沒有打開自己的思維。

這是一個社群的時代啊,在這里你應(yīng)該找到與你有相同價值觀但又互補的另一半。

譬如:你編程能力強,估值11分,如果以20分為最佳情侶來計算,你應(yīng)該找一個設(shè)計能力強,估值為9分的女生。

那么當(dāng)你遇到一個設(shè)計能力為9分的女生,千萬別猶豫,大膽去表白。千萬別以為后面的瓜比前面的甜哦。

舉個例子:有一個能力數(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) 的返回值應(yīng)該是0+3+1+2的和,即6。

function pairwise(arr, arg) {
    var flag = [];
    var sum = 0;

    for (var i=0; i<arr.length; i++){
        if (flag[i]){
            continue;
        }
        for (var j=i+1; j<arr.length; j++){
            if (flag[j]){
                continue;
            }
            if ((arr[i]+arr[j])===arg){
                flag[i] = true;
                flag[j] = true;
                sum += i;
                sum += j;
                break;
            }
        }
    }

    return sum;
}

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

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

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