freecodecamp中的16道Basic Algorithm Scripting

這裡還是先簡單介紹題目來這Learn to Code and Help Nonprofits.是一個很不錯的網站,下面是16道入門級演算法題,本人菜鳥一枚,這裡就分享下自己的解題思路和代碼。求大神親噴。

1.翻轉字元串

先把字元串轉化成數組,再藉助數組的reverse方法翻轉數組順序,最後把數組轉化成字元串。你的結果必須得是一個字元串。並提示了幾個用法

function reverseString(str) { return str;}reverseString("hello");

  • Global String Object
  • String.split()
  • Array.reverse()
  • Array.join()

解題代碼:

function reverseString(str) { var b ="";//創建空字元 for(i=1; i<str.length+1 ; i++){ var a = str[str.length-i] b +=a; } //倒序遍歷 return b; }

2.Factorialize a Number

計算一個整數的階乘

如果用字母n來代表一個整數,階乘代表著所有小於或等於n的整數的乘積。

function factorialize(num) { return num;}factorialize(5);

這是一道送分題就不多講了

解題代碼:

function factorialize(num) { if (num !== 0) { for(i=num-1;i>0;i--){ num *= i } return num; } return 1; }

3.Check for Palindromes

如果給定的字元串是迴文,返回true,反之,返回false。如果一個字元串忽略標點符號、大小寫和空格,正著讀和反著讀一模一樣,那麼這個字元串就是palindrome(迴文)。

function palindrome(str) { return true;}palindrome("eye");

提示:

  • String.replace()
  • String.toLowerCase()

解題思路:既然忽略大小寫,空格標點,我最先想到的是這個例子20122102和abcAcba.有點類似數列公式中的首項和末項,只需要比較這個字元的第1項和第N項是否相等,第2項和第n-1項。

解題代碼:

function palindrome(str){ //利用正則,替換掉非字母和數字的字元,並全部轉換成小寫 str = str.replace(/[^A-Za-z0-9]/g,"").toLowerCase(); for(var i = 0;i<str.length/2;i++){ //判斷。如果第i項不想等,返回false if(str[i] !==str[str.length-i-1]){ return false; } } return true }

4.Find the Longest Word in a String

找到提供的句子中最長的單詞,並計算它的長度。函數的返回值應該是一個數字。

function findLongestWord(str) { return str.length;}findLongestWord("The quick brown fox jumped over the lazy dog");

提示:

  • String.split()
  • String.length

解題思路:把字元分割成一個數組,設定一個初始值,在遍歷整個數組的每一個值。最後比較得出最大的長度值。

解題代碼:

function findLongestWord(str) { //分割字元,並返回一個數組 var arr = str.split(" "); var max = 0; for (var i = 0; i < arr.length; i++){ if (arr[i].length > max) { max = arr[i].length; } } return max; }

5.Title Case a Sentence

確保字元串的每個單詞首字母都大寫,其餘部分小寫。像"the"和"of"這樣的連接符同理。

function titleCase(str) {

return str;}titleCase("I"m a little tea pot");

提示:

  • String.split()

方法一、解題思路:當時看見這個分割就直接用了,拆分字元變成數組arr,在把arr[i]里的字元又拆分成單個字母的數組。再把arr[i][0]轉大寫,還要把其他arr[i][j]轉小寫。相當的繞。看代碼:

function titleCase(str) { var arr=str.split(" "); for(i=0;i<arr.length;i++){ arr2=arr[i].split(""); arr2[0]=arr2[0].toUpperCase(); for(j=1;j<arr2.length;j++){ arr2[j]=arr2[j].toLowerCase(); } arr[i]=arr2.join(""); } var newStr=arr.join(" "); return newStr;}

方法二、解題思路:還是要用到str.split(),分割成數組,這裡用到兩個兩個知識點arr.map(function(elem)和elem.substr(num).第一個是數組裡的一個方法。讓數組的每一個值去執行function並返回新的值,而substr是刪除字元串的第幾個值。我利用這個方法,可以直接將是·sKY這類字元直接轉換成Sky.來看代碼吧:

function titleCase(str) { var arr = str.split(" "); var Newarr; Newarr = arr.map(function(elem) { //重點就是這一步 return elem[0].toUpperCase()+elem.substr(1).toLowerCase(); }) var result = ""; for (var i = 0; i < Newarr.length; i++) { result += Newarr[i]+" ";//加空格是保證拼接成的是一個字元,而不是一大串英文 } result = result; return result = result.substring(0,result.length-1);//這裡再刪掉最後一個空格 }

方法三、解題思路:當寫完這兩個代碼以後,我才發現我「中計」了!艾瑪,我怎麼忘了正則?來感受下正則的威力吧,replace(reg, function(word) {}).重點就是這個。裡面寫一個函數,只將字元的首寫字母替換成大寫。這裡很多人可能會問,那其他字母大寫的什麼時候換成小寫了,別急,我一開始就把整個字元轉換成了小寫。看代碼

function titleCase(str) { //話說這個正則是在請教一位大神之後得出,我當時寫的存在一點小問題 return str.toLowerCase().replace(/([w|"]+)/g, function(word) { return word.replace(word.charAt(0), word.charAt(0).toUpperCase()); }); }

6.Return Largest Numbers in Arrays

右邊大數組中包含了4個小數組,分別找到每個小數組中的最大值,然後把它們串聯起來,形成一個新數組。

function largestOfFour(arr) { return arr;}largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);

提示:你可以用for循環來迭代數組,並通過arr[i]的方式來訪問數組的每個元素。

  • Comparison Operators

方法一、解題思路:這一次又被提示帶錯了路。你都提示我用戶for,好好好,我用我用我用還不行嗎?第一層循環,找出大數組中的小數組arr[i]。然後我還建立了一個findMax函數,用於第二層循環,找出小數組中的max= arr[i][j].然後把這些小數組中最大的值傳給一個newArr。這裡我用的是arr.concat().這裡提醒下,return 返回值放的位置一定不能搞錯了。放入小數組最大數進去的時候,一定在第一層循環里。切記!

解題代碼:

function largestOfFour(arr) { var Newarr = []; for(i=0;i<arr.length;i++){ function findMax(Arr){ for(j=1;j<Arr.length;j++){ //這裡找到最大值的函數寫法有很多種,如果看不懂這裡,參照第四題找最大字元串長度的寫法。 var max = Arr.reduce(function(prev,cur){ return cur>prev?cur:prev; }); } return max; } Newarr = Newarr.concat(findMax(arr[i])); } return Newarr }

方法二、解題思路:還是要用到arr.map(function(a){}).這裡還用一個高階函數Math.max.apply(null, a)。用法可以在MDN手冊上查。它的作用實際上就是方法一中的findMax.。但它還是是系統內置的方法,運算速度比上面快很多。

解題代碼:

function largestOfFour(arr) { return arr.map(function(a) { return Math.max.apply(null, a) }) }

7.Confirm the Ending

檢查一個字元串(str)是否以指定的字元串(target)結尾。如果是,返回true;如果不是,返回false。

function confirmEnding(str, target) { return str;}confirmEnding("Bastian", "n");//返回trueconfirmEnding("He has to give me a new name", "me");//返回trueconfirmEnding("He has to give me a new name", "na");//應該返回 false.

提示:

  • String.substr()

解題思路:又在XJB亂提示我,此處應有表情包。我可不中計了。看見匹配。首先想到的就是正則啊。老套路,拆分字元分割成一個數組。取數組最後一項arr[arr.length-1]和target比較。用正則的reg.test直接可返回布爾值。

解題代碼:

function confirmEnding(str, target) { var arr = str.split(" "); var laststr = arr[arr.length-1]; return (new RegExp(target + "$").test(str)); //上面的最後一行代碼可用這兩行替換。因為match無匹配值就返回null.這裡再利用三元運算符可求解 // var reg = new RegExp(target + "$"); // return str.match(reg) === null ? false : true; }

當然不會正則或者看不懂的小夥伴們也不用擔心,我們用substr也能解出來的。代碼:

function confirmEnding(str, target) {//容我再檢查這句代碼有沒有問題畢竟有點繞。因為不確定target需要測試幾個字元 所以要計算出截取對應個數的字元來var testStr = str.substr(str.length-target.length,str.length-target.length); if (testStr === target) { return true; }else{ return false; } }

8.Repeat a string repeat a string

重要的事情說3遍!重複一個指定的字元串 num次,如果num是一個負數則返回一個空字元串。

function repeat(str, num) { return str;}repeat("abc", 3);

提示:這是一道送分題,應該也就考察全局對象的。

  • Global String Object

解題思路:記住每次只累加一次str。所以要在循環外面定義個全局的str.

解題代碼:

function repeat(str, num) { a = str; if (num>0) { for(i=0;i<num-1;i++){ str +=a; } return str; } else{ return ""; } }

9.Truncate a string

截斷一個字元串!如果字元串的長度比指定的參數num長,則把多餘的部分用...來表示。

切記,插入到字元串尾部的三個點號也會計入字元串的長度。

但是,如果指定的參數num小於或等於3,則添加的三個點號不會計入字元串的長度。

function truncate(str, num) { return str;}truncate("A-tisket a-tasket A green and yellow basket", 11);

提示:

  • String.slice()

解題思路:主要就是去判斷num和str的長度關係。注意slice用法。其他好像也沒什麼好說的。直接看代碼吧

解題代碼:

function truncate(str, num) { if(num > 3 && str.length > num){ return newstr = str.slice(0,num-3) + "..."; } if(num > 3 && str.length < num || str.length === num){ return newstr = str; }else{ return newstr = str.slice(0, num) + "..." } }

10.Chunky Monkey

猴子吃香蕉可是掰成好幾段來吃哦!把一個數組arr按照指定的數組大小size分割成若干個數組塊。例如:chunk([1,2,3,4],2)=[[1,2],[3,4]];

chunk([1,2,3,4,5],2)=[[1,2],[3,4],[5]];

function chunk(arr, size) { return arr;}chunk(["a", "b", "c", "d"], 2);chunk([0, 1, 2, 3, 4, 5, 6], 3) 應該返回 [[0, 1, 2], [3, 4, 5], [6]]chunk([0, 1, 2, 3, 4, 5, 6, 7, 8], 4) 應該返回 [[0, 1, 2, 3], [4, 5, 6, 7], [8]]

提示:

  • Array.push()
  • Array.slice()

解題思路:其實這題用到的數學思維多一點,新數組應該包含幾個數組了?不能僅僅靠size來確定,因為後面2個例子,最後一個小數組裡的個數不等於size。而小數組的個數也不是靠size來確定的。這裡我用到上取整函數Math.ceil().第二個例子arr.length為7,每個小組裡的字元個數為3.那我就想到了7/3.再上取整就剛好是返回數組裡的slice()每次截取的位置也在變。因為當數組完成第一次分割,剩餘在裡面的個數也就發生了變化。所以slice(size*i,size*(i+1))里的兩個值要隨i值一起變化

解題代碼:

function chunk(arr, size) { var newArr = []; for(var i = 0; i < Math.ceil(arr.length/size);i++){ var temArr = arr.slice(size*i,size*(i+1)); newArr.push(temArr); } return newArr;}

11.Slasher Flick

返回一個數組被截斷n個元素後還剩餘的元素,截斷從索引0開始。

function slasher(arr, howMany) { return arr;}slasher([1, 2, 3], 2) 應該返回 [3].slasher([1, 2, 3], 0) 應該返回 [1, 2, 3].slasher([1, 2, 3], 9) 應該返回 [].

提示:

  • Array.slice()
  • Array.splice()

解題思路:沒有思路,送分題。直接看代碼

解題代碼:

function slasher(arr, howMany) { var removed = arr.splice(0, howMany); return arr;}

12.Mutations

如果數組第一個字元串元素包含了第二個字元串元素的所有字元,函數返回true。

舉例,["hello", "Hello"]應該返回true,因為在忽略大小寫的情況下,第二個字元串的所有字元都可以在第一個字元串找到。

["hello", "hey"]應該返回false,因為字元串"hello"並不包含字元"y"。

["Alien", "line"]應該返回true,因為"line"中所有字元都可以在"Alien"找到。

function mutation(arr) { return arr;}mutation(["hello", "hey"]);

提示:

  • String.indexOf()

方法一、解題思路:既然提示給了indexOf那我就索性用它吧。要求第二個字元的每一個字母都能在第一個字元里找到。且不區分大小寫。toLowerCase()轉換成小寫,遍歷var i= 0,indexOf(b[i])索引第二個字元的每一個值去比較。

代碼:

function mutation(arr) { var a = arr[0].toLowerCase(); var b = arr[1].toLowerCase(); for(var i = 0; i < b.length; i++){ if(a.indexOf(b[i]) < 0){ return false; } } return true;}

方法二、解題思路:既然提到匹配,比較。正則唄!但是這裡我至今還是沒有寫出完全符合題意的正則表達式。有兩個缺陷。下面看代碼的返回值就明白了。

代碼:

function mutation(arr) { var str = arr[1]; var re = new RegExp("["+arr[0]+"]","ig");//這個正則無法滿足下列2種情況,或者我不知道究竟能不能用正則來寫,希望有思路的朋友指點下 return re.test(str); }

mutation(["hello", "hey"])應該返回 false.

mutation(["hello", "neo"])應該返回 false.這兩個情況上訴代碼並依然返回true。求指教!!!!!

方法三、解題思路:由於上一個思路沒解出來,和一個小夥伴討論了很久這個思路有點繞,但是也刷新我的認知,那就是使用循環正則!既然我arr[1]中的每一個字母都能在arr[0]中找到,一旦有一個找不到就立馬返回false。否則返回true。下面看代碼再來好好解釋

代碼:

function mutation(arr) { var str = arr[0], re, flag = true; for (var i in arr[1]) { //通過i的變化來實現正則的變化,對應方法不能實現的第一個例子來說,這裡的正則分別是/h/,/e/,/y/,顯然當re=/y/時,測試結果返回false,循環不在繼續,立刻返回false re = new RegExp(arr[1][i], "ig"); if (re.test(str)) continue; else flag = false; } return flag; }

方法3很好的解決了方法2不能實現的問題,但是我堅信方法2可以使用最簡單的辦法,只是我想不出一個完美的正則來。好下一題

13.Falsy Bouncer

真假美猴王!刪除數組中的所有假值。在JavaScript中,假值有false、null、0、""、undefined 和 NaN。

function bouncer(arr) { return arr;}bouncer([7, "ate", "", false, 9]);

提示:

  • Boolean Objects
  • Array.filter()

解題思路:初看明顯是一道送分題,循環比較,判斷假值,刪除。這裡我用的是splice(i,1),就犯了錯誤,刪除一個數值,會跳過該值的下一個數,所以重點在每次刪除之後要給一個i--

解題代碼:

function bouncer(arr) { for(var i = 0;i<arr.length;i++){ if (!!arr[i]); else arr.splice(i,1) ,i--;//這裡的i--,是為了保證刪除掉一個元素的時,不影響下個元素測試,否則每刪除一次就會跳過一個元素} return arr; }

14.Seek and Destroy

實現一個摧毀(destroyer)函數,第一個參數是待摧毀的數組,其餘的參數是待摧毀的值。

function destroyer(arr) { return arr;}destroyer([1, 2, 3, 1, 2, 3], 2, 3) 應該返回 [1, 1]destroyer(["tree", "hamburger", 53], "tree", 53) 應該返回 ["hamburger"].

提示:

  • Arguments object
  • Array.filter()

解題思路:這題不知我沒明白出題者的意思還是,還是我對arguments對象沒理解。因為傳入的arr是一個對象,既不是數組,也不是字元串。但在當時我錯誤的理解了題意。所以用技巧過關。

解題代碼:

function destroyer(arr,str1,str2,str3){ for(var i = 0;i<arr.length;i++){ if (arr[i] !== str1 && arr[i] !== str2 && arr[i] !== str3); else arr.splice(i,1) ,i--; } return arr; }

這裡我完全是鑽了空子過關的。我講傳參優化成了一個數組和幾個字元串。正確的解題思路應該是

arr{Array:[]String:this.arr.Array[i]}

由於時間關係,日後我一定補上這道題正解!

15.Where do I belong

先給數組排序,然後找到指定的值在數組的位置,最後返回位置對應的索引。

舉例:where([1,2,3,4], 1.5) 應該返回 1。因為1.5插入到數組[1,2,3,4]後變成[1,1.5,2,3,4],而1.5對應的索引值就是1。

同理,where([20,3,5], 19) 應該返回 2。因為數組會先排序為 [3,5,20],19插入到數組[3,5,20]後變成[3,5,19,20],而19對應的索引值就是2。

function where(arr, num) { return num;}where([40, 60], 50);

提示:

  • Array.sort()

解題思路:這題其實很簡單,把num插入進arr,然後利用sort內嵌函數,按要求排序。最後找出和num相等的arr[i]下標值。

解題代碼:

function where(arr, num) { var newArr = arr.push(num); arr.sort(function(a, b){ return a - b; }); for(var i = 0; i < arr.length; i++){ if (arr[i] === num) break; } return i;}

16.Caesars Cipher

下面我們來介紹風靡全球的凱撒密碼Caesar cipher,又叫移位密碼。

移位密碼也就是密碼中的字母會按照指定的數量來做移位。

一個常見的案例就是ROT13密碼,字母會移位13個位置。由"A" ? "N", "B" ? "O",以此類推。

提示:

  • String.charCodeAt()
  • String.fromCharCode()

這是一道很經典的題,解法太多,思路也多。這裡我就粘貼一個大神的代碼吧。我自己寫實在太長太長,拿不出手。

function rot13(str) { return str.replace( /[A-Za-z]/g , function(c) { return String.fromCharCode( c.charCodeAt(0) + ( c.toUpperCase() <= "M" ? 13 : -13 ) ); } );}rot13("SERR PBQR PNZC");

我覺得我能夠看懂這段代碼已經很不錯了,也讓我知道了很多不足。

JavaScript演算法練習:Caesars Cipher _JavaScript學習筆記, JavaScript, JavaScript演算法練習 教程_w3cplus這是這 題一位大神的講解。直接戳這裡吧!

最後在CodeCombat中國推薦一個不錯學習代碼的方式,這是一款遊戲。前面是可以免費玩的。後面需要每個月9.9刀的費用。貼幾張圖給大家看看吧


推薦閱讀:

Web 後端第 7 期、Web 前端第 6 期報名公告
百分比進度條
我的「自學編程」過程

TAG:JavaScript | 前端开发 | 自学编程 |