Free Code Camp的JavaScript算法
翻轉(zhuǎn)字符串(Reverse a String
)
實現(xiàn):先把字符串轉(zhuǎn)化成數(shù)組,再借助數(shù)組的reverse方法翻轉(zhuǎn)數(shù)組順序眠冈,最后把數(shù)組轉(zhuǎn)化成字符串菌瘫。
function reverseString(str) {
newStr = str.split(""); //將字符串分割為單個字符雨让,并且每個字符作均作為數(shù)組的一個元素
newStrReverse = newStr.reverse(); //翻轉(zhuǎn)數(shù)組元素順序
strUnordered = newStrReverse.join(""); //連接數(shù)組的每個元素栖忠,沒有分隔符,組成一個字符串
return strUnordered;
}
reverseString("hello");
計算一個整數(shù)的階乘(Factorialize a Number
)
使用n
表示一個整數(shù)狸相,階乘代表所有小于或等于n
的整數(shù)的乘積脓鹃,階乘寫成n!
古沥。
n! = 1 * 2 * 3 * ... * (n-1) * n
。
function factorialize(num) {
if(num <= 1) {
return 1; //處理num為0和1的情況尊浓,0栋齿!等于1。
} else {
return num * factorialize(num - 1); //遞歸調(diào)用factorialize()函數(shù)
}
}
factorialize(5);
字符串回文(Check for Palindromes
)
01基协、搗鼓了一下午澜驮,終于把回文數(shù)弄出來了杂穷。之前一直卡在怎么匹配出不帶標點和空白的字符串上卦绣,finally還是找到了,就是個枚舉的正則表達式...順帶看了點正則表達式的知識廊蜒,明山叮、后天好好看看正則表達式的內(nèi)容添履。
02暮胧、就是找到了效率高一點的判斷回文數(shù)的方法
- 如果一個字符串忽略標點符號叔壤、大小寫和空格,順著讀和倒著讀相同嗅战,則這個字符串是回文
palindrome
俺亮。 - 需要去掉字符串的標點符號和空格脚曾,并且將字符串全部轉(zhuǎn)化為小寫(或大寫)來驗證字符串是否回文本讥。
function palindrome(str) {
//匹配所有標點符號(英文的)鲁冯,并且匹配所有空白符(/s)
var expression = /[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|<|\.|>|\/|\?|\s]+/g;
//使用replace()方法將所有標點和空白替換為空薯演,相當于將所有文本字符連接在一起跨扮;并且將所有字符轉(zhuǎn)化為小寫(不會改變原字符串)
var allChar = str.replace(expression, "").toLowerCase();
//將字符串分割為單子字符數(shù)組衡创,反轉(zhuǎn)數(shù)組晶通,再合并數(shù)組成一個字符串
var allLowerChar = allChar.split("").reverse().join(""); 录择、
//比較原字符串與反轉(zhuǎn)后字符串是否相同碗降,相同返回true讼渊,不同返回false
if(allLowerChar === allChar) {
return true;
} else {
return false;
}
}
palindrome("woca"); //調(diào)用
注:使用正則表達式expression = /[\~|\
|!|@|#|$|%|^|&|*|(|)|-|_|+|=|||\|[|]|{|}|;|:|"|'|,|<|.|>|/|?]+/g`可以匹配字符串中的所有標點符號爪幻。
去掉開頭的\ |
,用于匹配空格仇轻,使用后面的\s
來匹配所有的空白符篷店。
- 使用上述方法判斷回文字符串臭家,方便簡單钉赁,但是效率不高你踩,字符串的
split()
讳苦、reverse()
医吊、join()
需要很多額外的操作卿堂。 - 回文字符串的特點:第一個字符和最后一個字符相同草描,第二個字符和倒數(shù)第二個字符相同...(回文字符串從左向右或是從右向左讀都相同)
-
遞歸方法判斷--推薦方法
遞歸的作用在于不斷減小所處理問題的規(guī)模穗慕,直到可以解決為止妻导。
回文字符串問題:可以每次比較端部的字符倔韭,如果相同則去掉寿酌,再次比較端部字符醇疼;如果不同則返回false
。直到只剩中間的字符倔毙、或不剩下字符時陕赃,返回true
凯正。
function isPalindrome(str) {
var expression = /[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|<|\.|>|\/|\?|\s]*/g;
var allChar = str.replace(expression, "").toLowerCase();
for(var i = 0, j = allChar.length - 1; i < j; i++, j--) {
if(allChar.charAt(i) !== allChar.charAt(j)) {
return false;
} //.charAt(i)返回字符串索引為i位置的字符
}
return true; //如果執(zhí)行完循環(huán)沒有退出廊散,`str`為回文字符串
}
isPalindrome("ooaaoo");
找到句子中最長的單詞(Find the longest world in a string
)
- 找到提供的英文句子(字符串)中最長的單詞梧疲,并計算它的長度;函數(shù)返回值是一個數(shù)組胁澳。
- 自己的思路:將整個字符串以空格分割韭畸,構(gòu)建以每個單詞為元素的數(shù)組(字符串的
.split( )
方法)蔓搞;在根據(jù)單詞的長度排序整個數(shù)組喂分,最長的字符串在數(shù)組的端部蒲祈。
function findLongestWord(str) {
var strArray = str.split(" "); //轉(zhuǎn)化為以單詞為元素的數(shù)組扬卷,以空格為分隔符
var strSort = strArray.sort(function(a, b) {
return b.length - a.length; //遞減排序(如果a-b則是遞增排序)沥潭,看看`sort(a, b)`的文檔
});
var lenMax = strSort[0].length;
return lenMax;
}
findLongestWord("The quick brown fox jumped over the lazy dog");
- 可能存在的問題
1钝鸽、沒有去掉句子中的標點符號
2拔恰、當一個句子中有多個單詞長度相同時如何處理
function titleCase(str) {
return str.toLowerCase().split(' ').map(function(word) {
return word.charAt(0).toUpperCase() + word.slice(1);
}).join(' '); //先將字符串全部轉(zhuǎn)化為小寫颜懊,再以空格分割為以單詞為元素的數(shù)組河爹,然后將每個單詞的首字母大寫咸这,最后以空格連接每個元素媳维,重新組合為字符串。
}
titleCase("I'm a little tea pot");
返回數(shù)組中的最大值(Return Largest Numbers in Arrays
)
- 數(shù)組的元素是數(shù)值數(shù)組指黎,分別找到每個子數(shù)組的最大值,將其串聯(lián)起來形成一個新的數(shù)組州丹。
- 思路:寫一個函數(shù)
largeOne(arr1)
醋安,其功能是找到一個數(shù)組中的最大值,并將其返回墓毒;再寫另一個函數(shù)茬故,分別將每個數(shù)組作為參數(shù)傳入largeOne
,最后將得到的值添加到一個新的數(shù)組中.push()
方法蚁鳖。
//返回一個數(shù)組中的最大值
function largeOne(arr) {
var max = 0;
for(var i = 0; i < arr.length; i++) {
if(arr[i] > max) {
max = arr[i];
}
}
return max;
}
//分別迭代每個數(shù)組磺芭,把最大值添加到新的數(shù)組中
function largestOfFour(arr) {
var newArr = [];
for(var i = 0; i < arr.length; i++) {
newArr.push(largeOne(arr[i])); //選出最大的值并添加到新的數(shù)組中
}
return newArr;
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
檢查一個字符串的結(jié)尾(Confirm the Ending
)
- 檢查一個字符串
str
是否以指定的字符串target
結(jié)尾。 - 思路:利用
.slice()
方法醉箕,根據(jù)target
的長度,提取出str
的末尾部分,將之與target
比較间螟,如果相同返回true
。
function confirmEnding(str, target) {
if(str.slice(str.length - target.length, str.length) === target) { //忽略slice()的第二個參數(shù),默認提取到字符串的末尾
return true;
} else {
return false;
}
}
confirmEnding("Bastian", "n");
- 使用
.substr()
方法见坑,類似于slice()
方法。
function confirmEnding(str, target) {
if(str.substr(str.length - target.length) === target) {
return true;
} else {
return false;
}
}
confirmEnding("Bastian", "n");
重復(fù)一個字符串(Repeat a String
)
- 重復(fù)一個字符串
num
次,如果num
為負孙蒙,則返回一個空字符串香追。 - 思路:采用
+
操作符,可以連接+
左右兩邊的字符串,之間沒有空格凑队。使用一個for
循環(huán)實現(xiàn)疊加漩氨。
function repeat(str, num) {
var newStr = "";
if(num <= 0) {
return "";
} else {
for(var i = 0; i < num; i++) {
newStr += str;
}
}
return newStr;
}
repeat("abc", 3);
截斷字符串(Truncate a String
)
- 問題描述:如果字符串長度大于指定的參數(shù)
num
做修,則將多余的部分用...
表示。(插入帶字符串尾部的三個.
也會計入字符串長度步悠,但是如果參數(shù)num <= 3
答姥,則添加的三個.
不會計入字符串長度) - 思路:用一個
if
判斷字符串長度是否大于num
,如果false
則返回原字符串郎嫁;如果true
尚辑,在繼續(xù)判斷num
與3的關(guān)系,大于3時瓢喉,.
計入字符串的長度愕够;小于3時,.
不計入字符串長度擦秽。
function truncate(str, num) {
//如果字符串長度大于指定參數(shù)num
if(str.length > num) {
//如果參數(shù)num > 3
if(num > 3) {
return str.slice(0, num - 3) + "..."; //-3是三個.會計入字符串的長度
} else {
return str.slice(0, num) + "..."; //三個.不計入字符串長度
}
} else {
return str;
}
}
truncate("A-tisket a-tasket A green and yellow basket", 11);
將數(shù)組分割為若干塊(Chunky Monkey
)
- 把數(shù)組
arr
按照指定的size
分割成若干個數(shù)組塊触幼,例如chunk([1,2,3,4],2)=[[1,2],[3,4]];
,chunk([1,2,3,4,5],2)=[[1,2],[3,4],[5]];
。 - 思路:先分離
arr.length < size
和size <= 0
的情況谅阿,再利用.slice()
和.push()
操作,利用for
循環(huán)迭代提取arr
的數(shù)組塊,并添加到新數(shù)組中蔬墩。
function chunk(arr, size) {
var newStr = [];
var temp = [];
var len = arr.length;
if(len < size || size <= 0) {
return arr;
} else {
for(var i = 0; i < len; i += size) {
temp = arr.slice(i, i + size);
newStr.push(temp);
}
return newStr;
}
}
chunk(["a", "b", "c", "d"], 2);
注意:參考資料
Slasher Flick
- 返回一個數(shù)組被截斷
n
個元素后還剩余的元素樟插,截斷從索引0
開始食拜。 - 思路:直接采用數(shù)組的
.slice()
方法獲取元素組的后n
個元素,賦值給新的空數(shù)組。
function slasher(arr, howMany) {
if(arr.length < howMany) {
return [];
} else {
var newArr = arr.slice(-(arr.length-howMany)); //采用負索引奏篙,訪問數(shù)組的倒數(shù)元素
return newArr;
}
}
slasher([1, 2, 3], 2);
注:采用.splice()
方法充易,可以刪除原數(shù)組中的前n
個元素瑞妇。.splice()
會直接修改原數(shù)組改备。
function slasher(arr, howMany) {
if(arr.length < howMany) {
return [];
} else {
arr.splice(0, howMany); //參考MDNjs的文檔
return arr;
}
}
slasher([1, 2, 3], 2);
Mutations
- 如果數(shù)組第一個字符串元素包含了第二個字符串元素的所有字符(忽略大小寫)默勾,函數(shù)返回
true
环疼,否則返回false
阎曹。 - 采用[
indexOf()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf)方法锰霜,返回指定值在字符串對象中首次出現(xiàn)的位置友存。如果不存在,則返回
-1`。
function mutation(arr) {
var str1 = arr[0].toLowerCase();
var str2 = arr[1].toLowerCase();
var len = str2.length;
//遍歷str2的每個字符,如果有一個字符不在str1中,則返回false,如果全部通過,則返回true
for(var i = 0; i < len; i++){
if(str1.indexOf(str2[i]) === -1) {
return false;
}
}
return true;
}
mutation(["hello", "hey"]);
Falsy Bouncer
- 刪除數(shù)組中的所有假值(
false
崩溪、null
乳幸、0、undefined
、NaN
)端姚。 - 思路:采用
.filter()
方法,過濾掉返回值為false
的數(shù)組元素盆顾,不會改變原數(shù)組磷杏。參考Boolean Object
function isFake(element) {
if(element) {
return true;
} else {
return false;
}
}
function bouncer(arr) {
var newArr = arr.filter(isFake);
return newArr; //filter()方法不會改變原數(shù)組
}
bouncer([7, "ate", "", false, 9]);
Seek and Destroy
- 實現(xiàn)一個摧毀
destroy()
函數(shù)遥金,第一個參數(shù)是待摧毀的數(shù)組冲粤,其余的參數(shù)是待摧毀的值。 - 思路:使用
arguments.length
獲得傳入的參數(shù)個數(shù)锣笨,去掉第一個茅逮,剩下的為需要摧毀的值。使用.includes()
方法作為過濾函數(shù),判斷第一個數(shù)組參數(shù)中的每個元素是否出現(xiàn)在后面的參數(shù)中府寒,出現(xiàn)則過濾掉;其余分別.push()
到新的孔數(shù)組中剑令。
function destroyer(arr) {
var tempArr = [];
var newArr = [];
var len = arguments.length;
//構(gòu)建其余參數(shù)數(shù)組
for(var i = 1; i < len; i++) {
tempArr.push(arguments[i]); //使用arguments.length可以獲得傳入的參數(shù)數(shù)量
}
//遍歷第一個數(shù)組參數(shù),如果數(shù)組元素在tempArr中钾埂,則淘汰;如果不在印机,則增加到newArr中,最后得到淘汰后的數(shù)組
for(var j = 0; j < arguments[0].length; j++) {
if(!tempArr.includes(arguments[0][j])) {
newArr.push(arguments[0][j]);
}
}
return newArr; //使用arguments.length可以獲得傳入的參數(shù)個數(shù)
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
注:.filter()
方法沒有想出怎么實現(xiàn)。温眉。。
Where Do I Belong
- 先給數(shù)組排序躁倒,然后找到指定值在數(shù)組中的位置象迎,最后返回位置的索引劫乱。
- 野路子:先將元素添加到數(shù)組后面狭吼,再對數(shù)組排序谦趣,然后遍歷數(shù)組蔚润,找到插入的元素叉橱,最后循環(huán)變量
i
即是索引大磺。
function where(arr, num) {
// Find my place in this sorted array.
arr.push(num);
arr.sort(function(a, b) {
return a - b;
});
for(var i = 0; i < arr.length; i++) {
if(arr[i] === num) {
return i; //返回第一個值得索引
}
}
}
where([5, 3, 20, 3], 5);
Caesars Cipher
-
Caesars Cipher
又稱凱撒碼(位移碼),密碼中的字母按照指定的位數(shù)來做位移,密碼中的字母按照指定的數(shù)量來做位移翁潘。ROT13密碼:字母向后移動13個位置趁冈,A->N
,B->O
拜马,N->A
...渗勘,ROT13(ROT13(x)) == x
。 - 思路:先將字符串
.split("")
方法俩莽,將字符串中的每個字符分給為一個數(shù)組元素旺坠,然后遍歷數(shù)組元素。如果Unicode碼在[97, 122]之間(只有大寫字母)扮超,則按照算法向后推算取刃;如果不在,則保持原狀(空格和標點不處理)出刷。 - 方法:當Unicode碼在[65-77]之間時璧疗,直接每個加上13然后重新賦值;在[78-90]之間時馁龟,每個加上13崩侠,再減去26,最后賦值坷檩。
function rot13(str) { // LBH QVQ VG!
var newArr = str.split("");
var arr = [];
//大寫字母的Unicode碼從65到90
//如果在78-90之間却音,Unicode值減去13,改抡;在65-77之間,Unicode值加上13
//最后轉(zhuǎn)化為字符系瓢。
for(var i = 0; i < newArr.length; i++) {
if(newArr[i].charCodeAt() <= 90 && newArr[i].charCodeAt() >= 78) {
arr[i] = String.fromCharCode(newArr[i].charCodeAt() - 13);
} else if(newArr[i].charCodeAt() <= 77 && newArr[i].charCodeAt() >= 65) {
arr[i] = String.fromCharCode(newArr[i].charCodeAt() + 13);
} else {
arr[i] = newArr[i]; //不在65-90之間的不處理雀摘,略去空格和標點
}
}
return arr.join(""); //組合回字符串
}
// Change the inputs below to test
rot13("SERR PBQR PNZC");
居然做完了
哈哈,花了也不知道幾天的空余時間八拱,終于刷完了這點兒題阵赠,其中大部分都是自己完成,有些參考了網(wǎng)上的代碼肌稻,不過都是親手敲出來的碼清蚀,哈哈哈哈,自己居然能想出來爹谭!