FreeCodeCamp( FCC)前端工程師 基礎演算法練習 全解詳解 - 菜鳥的解答 ...
FreeCodeCamp 前端工程師 基礎演算法練習 全解 詳解
本人屬於很水的前端程式員中的一員,若文中有誤,敬請指正! 為了提升自己,同時看到基礎的還能應付,故而試之分享之!本文純屬於原創,轉載請聯繫 [email protected]!
// 第一章 反轉字元串
實現思路
先將字元串切分成數組 String.prototype.split('') 這裡括弧中的 '' 必要 否則切分無效 類似的用法還有 String.prototype.join('')
然後將該數組 Array.prototype.reverse() 返回翻轉後的數組
然後 Array.prototype.join('') 重新拼接數組並返回修改後的新的字元串
function reverseString(str) { return str.split('').reverse().join(''); } reverseString("hello");
//第二章 判斷是否迴文字元串
實現思路: 階乘 !n
遞歸調用自身直到 num === 0 再閉包往上返回每一層的結果
在 debugger 模式下(上帝視角) 我們可以清晰看到函數執行過程 JavaScript 解析器開始執行函數 在 call stack 中 壓入當前 factorialize 函數及其 local scope 數據
直到 num === 0 時 函數開始 retrun value 層層返回 併在調用函數完成之後從 call stack 中清除當前調用函數 並返回上次調用反正結果給當前 棧頂的 factorialize 使用
function factorialize(num) {
// 在非嚴格模式下可以使用 arguments.callee 調用自身
// TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
// return num === 0 ? 1 : arguments.callee(num-1) * num;
debugger; //(博主的 debugger 因為 freeCodeCamp 的 setTimeOut 進入了無限迴圈!!! WTF!) return num === 0 ? 1 : factorialize(num - 1) * num; } factorialize(5); //120
// 第三章 檢查字元串是否是迴文字元串
實現思路:
先處理原字元串 去掉非字元之外的內容 String.prototype.replace()
然後講字元串全部轉換成小寫字元方便比較 String.prototype.toLowerCase()
在用變數 str1 來緩存翻轉之後的字元串 思路與第一章一致
最後在 return str === str1 即可
function palindrome(str) { str = str.replace(/[^a-zA-Z0-9]/g, '').toLowerCase(); var str1 = str.split('').reverse().join(''); return str === str1; } palindrome("eye");
// 第四章 找到句子中最長的字元串
實現思路:
先將函數參數 str 根據 /\s/ 切分成數組 strArr
聲明一個哨兵變數 strLen = 0
再使用 Array.prototype.forEach() 判斷當前 item 的長度是否大於變數 strLen 如果大於 strLen 則對 strLen 重新賦值
最後在 forEach 迴圈完成之後 return strLen
function findLongestWord(str) { var strArr = str.split(/\s/); var strLen = 0; strArr.forEach(function(item){ if (item.length > strLen) { strLen = item.length; } }); return strLen; } findLongestWord("The quick brown fox jumped over the lazy dog");
// 第五章 將句中每個單詞首字母大寫
實現思路: 其實這個在很多支持組件 (component) 的庫中都有實現 比如:vue angualr react 錯了 汗 他們實現的是 屬性駝峰 和 a-b-c 此類組件名轉駝峰
通上一章 第一步先將函數參數 str 根據 /\s/ 切分成數組 strArr 隨後情況參數 str = ''
然後遍歷 strArr 中每一項 item.substr(0, 1).toUpperCase() 將每一項的第一個字母取出來並大寫 String.prototype.substr() 再調用 String.prototype.toUpperCase()
然後將每一項 字元串中除去第一個後 的字元並全部轉成小寫 item.slice(1).toLowerCase() String.prototype.slice()
如果當前項的索引不等於最後一項則 str += item + ' ' 否則 str += item
function titleCase(str) { var strArr = str.split(/\s/); str = ''; strArr.forEach(function(item, idx) {
// 這一步用這正則來實現應該更加舒心 有時間在去玩正則吧 item = item.substr(0, 1).toUpperCase() + item.slice(1).toLowerCase(); idx !== strArr.length -1 && (str += item + ' ') || (str += item); }); return str; } titleCase("I'm a little tea pot");
// 第六章 返回傳入數組中的最大數字
實現思路: 思路與第四章基本一致
function largestOfFour(arr) { // 首先傳入的是一個二維數組 // 其次比較傳入數組中每項數組的最大值然後push到新數組中 // 返回新數組 var maxArr = []; arr.forEach(function(arr) { // 局部變數或者稱之為哨兵變數 var maxNum = 0; arr.forEach(function(num){ if (num > maxNum) { maxNum = num; } }); // 內部arr forEach完成之後 maxNum 一定會是數組中最大值 maxArr.push(maxNum); }); // You can do this! return maxArr; } largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
// 第七章 檢查一個字元串(str
)是否以指定的字元串(target
)結尾。
實現思路: 在代碼中
實際上我認為我的寫法有點複查 如果各位看官有更好更簡單明瞭的寫法還請留言。
function confirmEnding(str, target) { // 首先判斷 str 是句子還是單詞 // 我們簡單根據 是否有 空格 來判斷 var isSentence = /\s/.test(str); // 然後判斷 target 是字母還是單詞 // 我們簡單根據 target.length 來判斷 如果 length > 1 則認為是單詞 var isWord = target.length !== 1; var strArr = [], lastChar = ''; // 如果是句子 則 target 應該是個單詞 // 否則判斷無效 或者 return null 或者 false // 如果 lastChar.length === targetLenth 我們則直接判斷 lastChar===target // 否則 我們截取 lastChar 指定的 target.length 再判斷 if (isSentence && isWord) { strArr = str.split(/\s/); lastChar = strArr.slice(-1)[0]; // 根據 target 長度來取 lastChar 的長度 if (lastChar.length !== target.length) { lastChar = lastChar.slice(target.length); } } else { // lastChar = str.substr(str.length-1, str.length); lastChar = str.slice(str.length-1); } // "Never give up and good luck will find you." // -- Falcor return lastChar === target; } confirmEnding("Bastian", "n");
// 第八章 重覆一個指定的字元串 num
次,如果num
是一個負數則返回一個空字元串。
function repeat(str, num) { var oldStr = str; str = ''; // 肯定需要迴圈當前的 num if (num > 0) { for(var i=0; i<num; i++) { str += oldStr; } } // repeat after me return str; } repeat("abc", 3);
// 第八章 如果字元串的長度比指定的參數num
長,則把多餘的部分用...
來表示。
function truncate(str, num) { // Clear out that junk in your trunk // 首先判斷給出的 num 是否大於 3 // 其次判斷給出的 num 是否大於 str.length 如果大於則返回原str if (num > 3) { if (num >= str.length) { return str; } str = str.replace(str.slice(num - 3), '...'); } else { str = str.replace(str.slice(num), '...'); } return str; } truncate("A-tisket a-tasket A green and yellow basket", 11);
// 第九章 把一個數組arr
按照指定的數組大小size
分割成若幹個數組塊。
function chunk(arr, size) { // 定義將返回的新數組 var newArr = []; // 求出新數組 根據 arr.length / size 的長度 // Math.ceil() 向上取整 var newArrLen = size < arr.length ? Math.ceil(arr.length / size) : 0; // 判斷 newArrLen 是否有效 if (newArrLen) { // 迴圈 Array.prototype.slice() 到新數組中 for (var i=0; i<newArrLen; i++) { newArr.push(arr.slice(i * size, (i+1) * size)); } } else { return arr; } // Break it up. return newArr; } chunk(["a", "b", "c", "d"], 2);
// 第九章 返回一個數組被截斷n
個元素後還剩餘的元素,截斷從索引0開始。
function slasher(arr, howMany) { // it doesn't always pay to be first return arr.slice(howMany); } slasher([1, 2, 3], 2);
// 第十章 如果數組第一個字元串元素包含了第二個字元串元素的所有字元,函數返回true。
function mutation(arr) { // 因為測試中所有的結果都有兩項 // 所以不考慮 arr存在大於兩項的情況 // 首先我們要分割 arr[0] 與 arr[1] 全部轉換成小寫 再使用 String.protottype.indexOf() 判斷 // 假設 isSame 為 true var str2Arr = arr[1].toLowerCase().split(''); var isSame = true; // 遍曆數組 str2Arr // 如果迴圈中檢測到 當前欄位不存在則 isSame = false for (var i=0, l=str2Arr.length; i<l; i++) { var str = str2Arr[i]; if (arr[0].toLowerCase().indexOf(str) < 0) { isSame = false; break; } } return isSame; } mutation(["hello", "hey"]);
// 第十一章 刪除數組中的所有假值
function bouncer(arr) { // Don't show a false ID to this bouncer. // 使用 Array.prototype.filter() 自動過濾掉 boolean(item) 為假的值 return arr.filter(function(item){ return item; }); } bouncer([7, "ate", "", false, 9]);
// 第十二章 實現一個摧毀(destroyer)函數,第一個參數是待摧毀的數組,其餘的參數是待摧毀的值。
function destroyer(arr) { // 參數數組 var args; // Remove all the values if (arguments.length > 1) { // Function.prototype.call() or Function.prototype.apply() args = Array.prototype.slice.call(arguments, 1, arguments.length); } else { return arr; } return arr.filter(function(item) { // 只有在args數組中的參數不存在arr中時才返回 Array.prototype.indexOf() // 這樣就過濾掉了那些待摧毀的值 return args.indexOf(item) < 0; }); } destroyer([1, 2, 3, 1, 2, 3], 2, 3);
// 第十三章 先給數組排序,然後找到指定的值在數組的位置,最後返回位置對應的索引。
function where(arr, num) { // Find my place in this sorted array. // 首先調用 Array.prototype.sort() 升序數組 傳入參數 compareFn // 然後迴圈數組 插入 num 返回當時的插入位置的索引 插入用 Array.prototype.splice() arr.sort(function(a, b){ return a>b ? 1 : -1; }); for (var i=0,l=arr.length; i<l; i++) { var previous = i !== 0 ? arr[i-1] : 0; var current = arr[i]; // 如果 num 大於 上一個值 小於 當前值 // 則就在該 i-1 處插入 num // 如果相等 就在 相等的值後面插入 num // 如果 num 一直大於數組中的每一項 那麼 num 就應該數組的最後一項插入 if (((num > previous && num < current) || num === current) || (i === l-1 && num > current)) { if (i === l-1 && num > current) { arr.splice(l, 0, num); num = l; } else { arr.splice(i, 0, num); num = i; } break; } } return num; } where([40, 60], 50);
寫到這裡真的很累了,不寫了。留下一題?no! 那還是做了吧!
// 第十四章 密碼中的字母會按照指定的數量來做移位。
// 這個趕時間 回去弄 下吃飯 身體重要 朋友!
總結
1. 這些真的很基礎,基礎到只要熟悉API就好!
2. 當然,由於是 JavaScript 的緣故,多多少少會有點小坑在!(畢竟我是菜鳥)
3.上面所有答案純屬個人見解,如果你有更好的解法,歡迎留言共同探討!
4. 博客純屬個人原創,轉載請聯繫本人! [email protected]!