記錄一下,F(xiàn)CC通關(guān)過(guò)程中,基礎(chǔ)算法,總共十五題。算是對(duì)些API的熟悉和對(duì)JS腳本結(jié)構(gòu)一些熟悉。
1.Reverse a String--翻轉(zhuǎn)字符串
要求:
先把字符串轉(zhuǎn)化成數(shù)組,再借助數(shù)組的reverse方法翻轉(zhuǎn)數(shù)組順序,最后把數(shù)組轉(zhuǎn)化成字符串。
結(jié)果必須得是一個(gè)字符串
思路:
- 直接split()拆分成數(shù)組
- 使用reverse()翻轉(zhuǎn)數(shù)組
- 通過(guò)join() 把數(shù)組拼成字符串。
function reverseString(str) {
var newstr = str.split("");
newstr.reverse();
str = newstr.join("");
return str;
}
reverseString("hello");
值得注意的是,join()應(yīng)該在參數(shù)中添加一個(gè)空字符創(chuàng),標(biāo)識(shí)直接連接。直接使用,則會(huì)使用默認(rèn),使用逗號(hào)“,”分隔。
寫的復(fù)雜了些,后來(lái)參照了別人的寫法,鏈?zhǔn)浇Y(jié)構(gòu),優(yōu)化了一下。
function reverseString(str) {
return str.split("").reverse().join("");
}
reverseString("hello");
2.Factorialize a Number--計(jì)算一個(gè)整數(shù)的階乘
要求:
如果用字母n來(lái)代表一個(gè)整數(shù),階乘代表著所有小于或等于n的整數(shù)的乘積。
思路:
- 計(jì)算階乘,從1開(kāi)始,聲明變量初始值 為1和 變量階乘總值
- 用for循環(huán),遍歷參數(shù)傳入的數(shù)值長(zhǎng)度,進(jìn)行累計(jì)相乘。
function factorialize(num) {
var i=1;
var all=1;
for( i=1; i<=num; i++){
all *=i;
}
return all;
}
factorialize(5);
3.Check for Palindromes--檢查回文字符串
要求:
如果給定的字符串是回文,返回true,反之,返回false。
如果一個(gè)字符串忽略標(biāo)點(diǎn)符號(hào)、大小寫和空格,正著讀和反著讀一模一樣,那么這個(gè)字符串就是palindrome(回文)。
思路:
- 檢查回文,需要對(duì)字符串進(jìn)行處理。轉(zhuǎn)換小寫(toLowerCase())、正則表達(dá)式處理特殊字符,然后拆分為數(shù)組(split())。
- 拆分為數(shù)組后,翻轉(zhuǎn)數(shù)組(reverse()),合拼為字符串(jion()).
- 把合拼成的字符串和傳入的參數(shù)字符串進(jìn)行對(duì)比判斷。
function palindrome(str) {
var movestr = str.replace( /\W+/g ,''); //正則表達(dá)式篩選所有非單詞字符,替換為空的字符串
movestr = movestr.replace(/\_+/g,''); //正則表達(dá)式篩選所有下劃線字符,替換為空的字符串
movestr = movestr.toLowerCase();
var spstr = movestr.split('');
var restr = spstr.reverse();
var newstr = restr.join('');
if(newstr===movestr){
return true;
}
else{
return false;
}
}
palindrome("eye");
第一次按思路實(shí)現(xiàn),雖然實(shí)現(xiàn)了,但是寫得很丑,嘗試進(jìn)行優(yōu)化,兩個(gè)優(yōu)化的思路:
其一:
function palindrome(str) {
str = str.replace(/[^A-Za-z0-9]/g,'').toLowerCase(); //正則表達(dá)式直接索引匹配以A-Z、a-z、0-9字符串和數(shù)字開(kāi)始的,字符串轉(zhuǎn)換為小寫
for(var i=0;i<str.length/2;i++){ //取字符串一半的長(zhǎng)度,進(jìn)行循環(huán)
if(str[i]!==str[str.length-i-1]){ //對(duì)字符串對(duì)應(yīng)位置根據(jù)回文規(guī)則判斷,是否相等(第一位對(duì)最后一位,第二位對(duì)倒數(shù)第二位,以此類推)
return false;
}
}
return true;
}
palindrome("eye");
其二:
function palindrome(str) {
var re = /[\W\s_]/gi; // 轉(zhuǎn)義字符\W,非單詞字符和空白字符并且不區(qū)分大小寫
str = str.replace(re,"");
return str.toLowerCase() === str.split("").reverse().join("").toLowerCase();
}
palindrome("eye");
主要還是正則表達(dá)式的處理,花去了許多時(shí)間。正則還是很弱,得加強(qiáng)。
4.Find the Longest Word in a String -- 找出最長(zhǎng)單詞
要求:
在句子中找出最長(zhǎng)的單詞,并返回它的長(zhǎng)度。
函數(shù)的返回值應(yīng)該是一個(gè)數(shù)字。
思路:
- 拆分句子,把字符串拆分為一段段字符串,句子間使用空格拆分(split(' ')),保存在數(shù)組中。
- 聲明一個(gè)初始值,對(duì)數(shù)組進(jìn)行遍歷,初始值和每一段字符串的length長(zhǎng)度比較,較大的就賦值給初始值。遍歷后初始值可得到最大的值。
function findLongestWord(str) {
var newstr =str.split(" "); // 字符串拆分為數(shù)組,空格間隔
var longWord = 0; //設(shè)置初始最小值
for(var i=0; i<newstr.length;i++){ // for循環(huán),比較出長(zhǎng)度最長(zhǎng)的單詞
if(newstr[i].length>longWord){
longWord=newstr[i].length;
}
}
return longWord;
}
findLongestWord("The quick brown fox jumped over the lazy dog");
按思路來(lái),總是寫不夠好,還是得優(yōu)化一下:
function findLongestWord(str) {
var arr=str.split(" "); // 字符串拆分為數(shù)組,空格間隔
arr=arr.map(function(item){// map方法匹配出數(shù)組中各個(gè)字符串的長(zhǎng)度,返回字符創(chuàng)長(zhǎng)度
return item.length;
}).sort(function(a,b){ // sort()函數(shù)方法由大到小按順序排序數(shù)字,
return b-a;
});
return arr[0]; // 返回第一個(gè)最大數(shù)字
}
5.Title Case a Sentence--句中單詞首字母大寫
要求:
句中單詞首字母大寫
確保字符串的每個(gè)單詞首字母都大寫,其余部分小寫。
像'the'和'of'這樣的連接符同理。
思路:
- 先拆分句子,單獨(dú)修改每一段字符串的首字母為大寫,其余為小寫。
- 把大小寫轉(zhuǎn)化后的字符串,轉(zhuǎn)化回句子。
function titleCase(str) {
var str1=str.split(" ");//拆分字符串為數(shù)組
var str2;
var newstr;
for(var i=0; i < str1.length;i++){
str2=str1[i].split(""); //循環(huán)數(shù)組str1單詞,拆分至數(shù)組str2單字符
str2[0] = str2[0].toUpperCase(); //數(shù)組str2單字符首字符大寫
for(var j=1;j < str2.length;j++){ //數(shù)組str2單字符其余字符小寫
str2[j] = str2[j].toLowerCase();
}
str1[i] = str2.join(""); //單字符數(shù)組合并為單詞;
}
newstr = str1.join(" "); //單詞數(shù)組合并為字符串;
return newstr;
}
titleCase("I'm a little tea pot");
嗯恩恩.....還是得優(yōu)化一下,兩個(gè)for循環(huán),感覺(jué)寫了一長(zhǎng)串。
function titleCase(str) {
//toLowerCase()全部轉(zhuǎn)化為小寫、split()拆分字符串為數(shù)組、map()方法返回一個(gè)新數(shù)組;
var newstr=str.toLowerCase().split(" ").map(function(item){
return item[0].toString().toUpperCase()+item.slice(1);
//獲取數(shù)組的第一個(gè)字母,轉(zhuǎn)化為大寫
//然后加上后面的小寫內(nèi)容(slice()方法獲取范圍內(nèi)容,1表示從第二個(gè)字母開(kāi)始)
}).join(" "); //join()方法組合成字符串
return newstr;
}
titleCase("I'm a little tea pot");
6. Return Largest Numbers in Arrays--找出多個(gè)數(shù)組中的最大數(shù)
要求:
找出多個(gè)數(shù)組中的最大數(shù)
右邊大數(shù)組中包含了4個(gè)小數(shù)組,分別找到每個(gè)小數(shù)組中的最大值,然后把它們串聯(lián)起來(lái),形成一個(gè)新數(shù)組。
思路:
- 多重?cái)?shù)組,先把子數(shù)組進(jìn)行處理。遍歷大數(shù)組,先對(duì)每個(gè)子數(shù)組進(jìn)行排序。
- 把每個(gè)排序后的子數(shù)組,最大的添加到新數(shù)組。
function largestOfFour(arr) {
var newArr=[];
for(var i=0;i<arr.length;i++){
arr[i].sort(function(a,b){
return b-a;
});
newArr.push(arr[i][0]);
}
return newArr;
}
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
7. Confirm the Ending--檢查字符串結(jié)尾
要求:
判斷一個(gè)字符串(str)是否以指定的字符串(target)結(jié)尾。
如果是,返回true;如果不是,返回false。
提示:String.substr()
思路:
- 思路很簡(jiǎn)單,直接獲取要對(duì)比結(jié)尾字符串的長(zhǎng)度,然后在長(zhǎng)字符串中,找到對(duì)應(yīng)長(zhǎng)度的結(jié)尾,進(jìn)行對(duì)比。
function confirmEnding(str, target) {
var starLen =str.length - target.length;
var strArr=str.substr(starLen);
if(strArr===target){
return true;
}
else{
return false;
}
}
confirmEnding("Bastian", "ian");
也可以用前面用到過(guò)的slice()方法,
slice(star,end), start負(fù)數(shù)表示從字符串末尾開(kāi)始算,end為可選,結(jié)束標(biāo)
比如:
var str=“abcd”;
var newstr=str.slice(-2)
newstr
優(yōu)化了一下,感覺(jué)也還可以。
function confirmEnding(str, target) {
if(str.substr(-target.length) === target){
return true;
}
else{ return false; }
}
confirmEnding("Bastian", "n");
8. Repeat a string repeat a string--重復(fù)輸出字符串
要求:
重復(fù)輸出字符串 (重要的事情說(shuō)3遍)
重復(fù)一個(gè)指定的字符串 num次,如果num是一個(gè)負(fù)數(shù)則返回一個(gè)空字符串。
--
思路:
1.思路挺清晰的,重復(fù)輸出n次字符串,n為負(fù)數(shù)則返回空字符串;
function repeat(str, num) {
var newstr =str;
if(num >= 0){
for(var i=0;i<num-1; i++){
str+= newstr;
}
return str;
}
else{ return ""}
}
repeat("abc", 3);
后面思考了一下,把多一個(gè)if判斷可以省略掉。
function repeat(str, num) {
var newStr='';
for(var i=1;i<=num;i++){
newStr+=str;
}
return newStr;
}
9. Truncate a string--截?cái)嘧址?/h4>
要求:
截?cái)嘧址?br>
(用瑞茲來(lái)截?cái)鄬?duì)面的退路)
如果字符串的長(zhǎng)度比指定的參數(shù)num長(zhǎng),則把多余的部分用...來(lái)表示。
切記,插入到字符串尾部的三個(gè)點(diǎn)號(hào)也會(huì)計(jì)入字符串的長(zhǎng)度。
但是,如果指定的參數(shù)num小于或等于3,則添加的三個(gè)點(diǎn)號(hào)不會(huì)計(jì)入字符串的長(zhǎng)度。
提示:slice()
思路:
- 進(jìn)行兩步判斷,判斷字符串是否大于給定的數(shù)值,大于則進(jìn)行下一步判斷,小于則直接返回。
- 當(dāng)判斷字符串大于給定數(shù)值,則再進(jìn)行判斷是是否大于最小值3。
function truncate(str, num) {
var newStr= "";
if(str.length>num){
if(num<=3){
newStr =str.slice(0,num)+"...";
}
else{
newStr =str.slice(0,num-3)+"...";
}
return newStr;
}
else{
return str;
}
}
truncate("A-tisket a-tasket A green and yellow basket", 11);
稍微簡(jiǎn)化了一下
function truncate(str, num) {
var result='';
if(str.length<=num){
result=str;
}else{
result=num>3?str.slice(0,num-3)+'...':str.slice(0,num)+'...';
}
return result;
}
truncate("A-tisket a-tasket A green and yellow basket", 11);
10.Chunky Monkey-- 分割數(shù)組,猴子吃香蕉
要求:
猴子吃香蕉, 分割數(shù)組
(猴子吃香蕉可是掰成好幾段來(lái)吃哦)
把一個(gè)數(shù)組arr按照指定的數(shù)組大小size分割成若干個(gè)數(shù)組塊。
例如:chunk([1,2,3,4],2)=[[1,2],[3,4]];
chunk([1,2,3,4,5],2)=[[1,2],[3,4],[5]];
提示:Array.push()、Array.slice()
思路:
- 把數(shù)組分塊,就先把數(shù)組拆分成指定數(shù)組快,然后添加到一個(gè)新數(shù)組中。
function chunk(arr, size) {
var newArr=[];
for(var i=0; i<arr.length;i+=size){
newArr.push(arr.slice(i,i+size));
}
return newArr;
}
chunk(["a", "b", "c", "d"], 2);
11.Slasher Flick-- 截?cái)鄶?shù)組
要求:
返回一個(gè)數(shù)組被截?cái)鄋個(gè)元素后還剩余的元素,截?cái)鄰乃饕?開(kāi)始。
提示:Array.slice()、Array.splice()
思路:
- 挺簡(jiǎn)單的,主要是熟悉使用api,這里使用兩個(gè)api都可以實(shí)現(xiàn)。
用slice()
function slasher(arr, howMany) {
return arr.slice(howMany);
}
slasher([1, 2, 3], 2);
用splice()
function slasher(arr, howMany) {
arr.splice(0,howMany);
return arr;
}
slasher([1, 2, 3], 2);
12.Mutations--比較字符串
要求:
比較字符串
(蛤蟆可以吃隊(duì)友,也可以吃對(duì)手)
如果數(shù)組第一個(gè)字符串元素包含了第二個(gè)字符串元素的所有字符,函數(shù)返回true。
舉例,["hello", "Hello"]應(yīng)該返回true,因?yàn)樵诤雎源笮懙那闆r下,第二個(gè)字符串的所有字符都可以在第一個(gè)字符串找到。
["hello", "hey"]應(yīng)該返回false,因?yàn)樽址?hello"并不包含字符"y"。
["Alien", "line"]應(yīng)該返回true,因?yàn)?line"中所有字符都可以在"Alien"找到。
提示:indexOf()
思路:
- 好像沒(méi)有什么思路,按照要求一步步寫下來(lái)。
indexOf() 方法返回調(diào)用 String 對(duì)象中第一次出現(xiàn)的指定值的索引,開(kāi)始在 fromIndex進(jìn)行搜索。
如果未找到該值,則返回-1
function mutation(arr) {
arr[0]=arr[0].toLowerCase();
arr[1]=arr[1].toLowerCase();
for(var i=0;i<arr[1].length; i++){
if(arr[0].indexOf(arr[1][i])==-1){
return false;
}
}
return true;
}
mutation(["hello", "hey"]);
13.Falsy Bouncer--過(guò)濾數(shù)組假值
要求:
過(guò)濾數(shù)組假值
(真假美猴王)
刪除數(shù)組中的所有假值。
在JavaScript中,假值有false、null、0、""、undefined 和 NaN。
提示:Boolean Objects 、Array.filter()
思路:
- 通過(guò)Boolean判斷是否為true值,如果符合,就返回到新數(shù)組。Array.fillter()就可以實(shí)現(xiàn)。
arr = arr.filter(filterFalsy);
function filterFalsy(item){
return Boolean(item) === true;
}
return arr;
bouncer([7, "ate", "", false, 9]);
14.Seek and Destroy--摧毀數(shù)組
要求:
摧毀數(shù)組
金克斯的迫擊炮!
實(shí)現(xiàn)一個(gè)摧毀(destroyer)函數(shù),第一個(gè)參數(shù)是待摧毀的數(shù)組,其余的參數(shù)是待摧毀的值。
提示:Arguments object 、Array.filter()Array.filter()
思路:
- 通過(guò)arguments 判斷出有參數(shù)個(gè)數(shù),然后作為循環(huán)條件
- Array.filter()篩選掉傳進(jìn)來(lái)的參數(shù),把剩下的返回。
function destroyer(arr) {
var arg =arguments;
for(var i =1;i<arg.length;i++){
arr = arr.filter(function(x){
return x!==arg[i];
});
}
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
15.Where do I belong--數(shù)組排序找索引
要求:
數(shù)組排序并找出元素索引
我身在何處?
先給數(shù)組排序,然后找到指定的值在數(shù)組的位置,最后返回位置對(duì)應(yīng)的索引。
舉例:where([1,2,3,4], 1.5) 應(yīng)該返回 1。因?yàn)?.5插入到數(shù)組[1,2,3,4]后變成[1,1.5,2,3,4],而1.5對(duì)應(yīng)的索引值就是1。
同理,where([20,3,5], 19) 應(yīng)該返回 2。因?yàn)閿?shù)組會(huì)先排序?yàn)?[3,5,20],19插入到數(shù)組[3,5,20]后變成[3,5,19,20],而19對(duì)應(yīng)的索引值就是2。
提示:sort()
思路:
- 先把要添加的數(shù)字push到數(shù)組中,然后用sort()再進(jìn)行排序,然后用indexOf()找出索引。
function where(arr, num) {
arr.push(num);
arr.sort(function(a,b){return a-b;});
return arr.indexOf(num);
}
where([40, 60], 50);
16.Caesars Cipher--凱撒密碼
要求:
凱撒密碼
(讓上帝的歸上帝,凱撒的歸凱撒)
下面我們來(lái)介紹風(fēng)靡全球的凱撒密碼Caesar cipher,又叫移位密碼。
移位密碼也就是密碼中的字母會(huì)按照指定的數(shù)量來(lái)做移位。
一個(gè)常見(jiàn)的案例就是ROT13密碼,字母會(huì)移位13個(gè)位置。由'A' ? 'N', 'B' ? 'O',以此類推。
寫一個(gè)ROT13函數(shù),實(shí)現(xiàn)輸入加密字符串,輸出解密字符串。
所有的字母都是大寫,不要轉(zhuǎn)化任何非字母形式的字符(例如:空格,標(biāo)點(diǎn)符號(hào)),遇到這些特殊字符,跳過(guò)它們。
提示:charCodeAt() 、String.fromCharCode()
思路:
- ROT13的思路入手,先把傳入字符串參數(shù)的每個(gè)字符拆分成Unicode,保存在一個(gè)數(shù)組中。
- 對(duì)這個(gè)數(shù)組進(jìn)行處理,處于大寫字母的Unicode碼區(qū)間是65~90,遍歷數(shù)組,不符合這個(gè)范圍的直接返回。
- 符合范圍的,進(jìn)行ROT13的規(guī)則進(jìn)行處理,每一個(gè)Unicode碼值加上13,超出范圍后,重頭開(kāi)始。
寫出來(lái)的第一版:
function rot13(str) {
var arr=[];
var arr2=[];
for(var i =0;i<str.length;i++){
arr.push(str.charCodeAt(i));
}
arr = arr.map(function(x){
if(x<65 || x>90){
return x;
}
else{
if(x+13>90){
return x+13-26;
}
else{
return x+13;
}
}
});
for(var j = 0; j<arr.length;j++){
arr2.push(String.fromCharCode(arr[j]));
}
str =arr2.join('');
return str;
}
rot13("SERR PBQR PNZC");
進(jìn)行優(yōu)化后:
function rot13(str) {
var arr =[];
for(var i=0;i<str.length;i++){
if(str.charCodeAt(i)<65 ||str.charCodeAt(i)>90){
arr.push(String.fromCharCode(str.charCodeAt(i)));
}
else if(str.charCodeAt(i)>77){
arr.push(String.fromCharCode(str.charCodeAt(i)-13));
}
else{
arr.push(String.fromCharCode(str.charCodeAt(i)+13));
}
}
return arr.join('');
}
rot13("SERR PBQR PNZC");
完成啦。過(guò)完這十六道很基礎(chǔ)題,學(xué)到了不少東西。