FreeCodeCamp - Basic Algorithm Scripting

FreeCodeCamp - Basic Algorithm Scripting

这一部分真的要做笔记了,要不然又会忘掉。

Reverse a String

翻转字符串

先把字符串转化成数组,再借助数组的reverse方法翻转数组顺序,最后把数组转化成字符串。

你的结果必须得是一个字符串

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function reverseString(str) {
  str = str.split("").reverse().join("");
  return str;
}

reverseString("hello");

str.split() 是将对象分割成字符串数组。

reverse() 颠倒数组串中的元素位置,第一个元素会成为最后一个,最后一个会成为第一个。

join() 将数组的元素链接到一个字符串中。

括号中的 "" 是分割数组,例如:

function myFunction(){
    var str="How are you doing today?";
    var n=str.split("");
    return n;
}

输出:H,o,w, ,a,r,e, ,y,o,u, ,d,o,i,n,g, ,t,o,d,a,y,?

Factorialize a Number

计算一个整数的阶乘

如果用字母n来代表一个整数,阶乘代表着所有小于或等于n的整数的乘积。

阶乘通常简写成 n!

例如: 5! = 1 * 2 * 3 * 4 * 5 = 120

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function factorialize(num) {
  if (num<2) {
    return 1;
  }
  for(var i=1,result=1;i<=num;i++) {
    result = result*i;
  }
  return result;
}

factorialize(5);
//i<=0是循环0次啊大哥,所以factorialize(0)时直接就是 i=1,recult=1了 

这题要这样想,0! 和 1! 都是1,所以要搞一个 if 函数来设定 num 小于 0 时结果为 1。

关于 for 循环,通常是先赋予 i 一个值,让 i 小于或大于一个值或者长度,用 i++ i-- 来循环。

Check for Palindromes

如果给定的字符串是回文,返回true,反之,返回false

如果一个字符串忽略标点符号、大小写和空格,正着读和反着读一模一样,那么这个字符串就是palindrome(回文)。

注意你需要去掉字符串多余的标点符号和空格,然后把字符串转化成小写来验证此字符串是否为回文。

函数参数的值可以为"racecar""RaceCar""race CAR"

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function palindrome(str) {
  // Good luck!
  var arr = str.toLowerCase().replace(/[^a-z0-9]/g,"");
  var reversearr = arr.split("").reverse().join("");
  if (arr == reversearr) {
    return true;
  } else {
    return false;
  }
}



palindrome("eye");

网上大神有详尽的正则表达式的解释

关于正则

在给出答案之前,先简单说说这道题的正则如何写最好

在这道题目中,我们需要把空格、特殊符号都去掉。.replace() 方法接收的第一个参数为一个正则表达式(或字符),第二个参数为字符(或一个 function)。作用就是把通过第一个参数匹配到的字符给替换成第二个参数的字符。括号中的参数类型,这道题中并不会用到

那么,我们需要做的就是,在第一个参数中匹配空格和特殊符号,第二个参数中传入 "" 空字符,顺便,记得要在正则结尾写上 /g,否则不能替换全部

匹配空格和特殊符号,空格是 \s (请注意,反之不成立,\s 不光是空格,还包括制表符 tab,以及换行符 \r 或者 \r\n)。然而,特殊符号,并没有一个通用的匹配写法

有些朋友可能会想这样做,事实上我也真的见过有不少人这样做:/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/g,嗯,没毛病

但我们换一种思路想想,其实我们要做的,就是"保留英文字母和数字"。这样,正则就变得简单很多了,只需要 /[^A-Za-z0-9]/g。另一方面,如果你先 .toLowerCase().replace(),正则就可以直接写成 /[^a-z0-9]/g

如果你决定用 \w 的相反形式 \W,没有问题,但一定要记住,\w 不仅包含英文字母,还包含了下划线 _。因此,你需要写成 /[\W_]/g,或者写成 /\W|_/g

toLowerCase() 会将调用该方法的字符串值转为小写形式,并返回。

replace() 方法返回一个由替换值替换一些或所有匹配的模式后的新字符串。模式可以是一个字符串或者一个 正则表达式 , 替换值可以是一个字符串或者一个每次匹配都要调用的函数。

这里的难点估计就是正则表达式了,我们来看这段代码:

var arr = str.toLowerCase().replace(/[^a-z0-9]/g,"");

/[^a-z0-9] 代表的意思是除了 26 个字母和所有数字。

/g 代表全局匹配,如果不加,则只会匹配第一个元素。

.replace(/[^a-z0-9]/g,""); 所以这句话的意思是,把除了 26 个字母和所有数字的其他元素全部换成 ""

Find the Longest Word in a String

找到提供的句子中最长的单词,并计算它的长度。

函数的返回值应该是一个数字。

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function findLongestWord(str) {
  var strArr = str.split(" ");
  var max = strArr[0].length;
  for (i=0;i<strArr.length;i++) {
    if (strArr[i].length>=max) {
      max = strArr[i].length;
    }
  }
  return max;
}

findLongestWord("The quick brown fox jumped over the lazy dog");

先使这段语句成为数组,用 str.split(" ")

赋予 maxstrArr[0].length ,即数组第一个单词的长度。

for 函数历遍数组中的所有元素

如果元素(即 strArr[i].length )的长度比 max 大,就会更新 max 函数。

Title Case a Sentence

确保字符串的每个单词首字母都大写,其余部分小写。

像'the'和'of'这样的连接符同理。

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

其实这一题不光有 String.split() 还不够,还要有:

我的解法:

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

titleCase("I'm a little tea pot");

这里主要是 slice() 不太懂,这是代表提取字符串的一部分,并返回一新的字符串。

slice(1) 就是代表提取字符串从 2 开始的到最后一个字符。

substr() 是返回一个字符串中从指定位置开始到指定字符数的字符。

slice()substr() 可以互换。

Return Largest Numbers in Arrays

右边大数组中包含了4个小数组,分别找到每个小数组中的最大值,然后把它们串联起来,形成一个新数组。

提示:你可以用for循环来迭代数组,并通过arr[i]的方式来访问数组的每个元素。

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function largestOfFour(arr) {
  // You can do this!
  var maxArr = [];
  for (var i=0;i<arr.length;i++) {
    var max = arr[i][0];
    for (var j=0;j<arr[i].length;j++) {
      if (arr[i][j]>=max) {
        max=arr[i][j];
      }
    }
    maxArr[i]=max;
  }
  return maxArr;
}

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

这道题是这样的,先设置一个空的数组 maxArr

for 函数历遍 arr。赋予 max 为每个 arr[i] 元素里面的第一个元素

再用 for 函数历遍 arr[i] ,如果 arr[i][j]>=max ,刷新 max

max 返回 maxArr[i]

得出数组

Confirm the Ending

检查一个字符串(str)是否以指定的字符串(target)结尾。

如果是,返回true;如果不是,返回false。

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function confirmEnding(str, target) {
  // "Never give up and good luck will find you."
  // -- Falcor
  var last = str.substr(str.length-target.length);
  if (last == target){
    return true;
  }
  return false;
}

confirmEnding("Bastian", "n");

例题中 str.length-target.length 得出来的是 5 ,即从 6 个字符开始算,last 得到 n

Repeat a string repeat a string

重要的事情说3遍!

重复一个指定的字符串 num次,如果num是一个负数则返回一个空字符串。

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function repeat(str, num) {
  // repeat after me
  var arr = "";
  for (i=0;i<num;i++) {
    arr += str;
  }
  return arr;
}

repeat("abc", 3);

估计我对 for 函数没有那么熟悉吧,这道题搞得我一蒙一蒙的。。

arr += str; 是指 arr = arr + str ,num 有多大,这条式子就循环多少次。

Truncate a string

用瑞兹来截断对面的退路!

截断一个字符串!

如果字符串的长度比指定的参数num长,则把多余的部分用...来表示。

切记,插入到字符串尾部的三个点号也会计入字符串的长度。

但是,如果指定的参数num小于或等于3,则添加的三个点号不会计入字符串的长度。

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function truncate(str, num) {
  // Clear out that junk in your trunk
  if (str.length<=num) {
    return str;
  } else {
    if (num<=3) {
      return str.slice(0,num)+"...";
    } else {
      return str.slice(0,num-3)+"...";
    }
  }
}

truncate("A-tisket a-tasket A green and yellow basket", 11);

这里主要运用了 str.slice() 的函数

如果语句的长度小于等于 num 则直接返回 str

如果不是,这里要分两种情况,一种是比 num 大于等于 3 。一种是 num 小于 3的情况

因为 truncate(str, num)num 是包括小数点的,小数点占 3 位,而题目要求的是如果指定的参数num小于或等于3,则添加的三个点号不会计入字符串的长度

所以条件 if 设为 if (num<=3) { return str.slice(0,num)+"...";}

这样的话,假如是 truncate(abcd, 2) 。会返回 "ab..."

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]];

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function chunk(arr, size) {
  // Break it up.
  var result=[];
  for (var i=0;i<arr.length;i+=size) {
    var temp=[];
    for (var j=i;j<i+size;j++) {
      if (j<arr.length) {
        temp.push(arr[j]);
      }
    }
    result.push(temp);
  }
  return result;
}

chunk(["a", "b", "c", "d"], 2);

我自己是这样理解的,假如 size 是 2,arr[1,2,3]

那第一个 for 循环到 4 就会推出

设一个临时数组 temp

所以 temp 会有两 [] 因为循环两次退出

i+=size 会加到 2 就停止,所以就只会到 2

所以会 temp.push(arr[2]) 就是 [1,2]

剩下不是还有一个 3 么,它会作为一个余数加到 temp

所以返回数组 [[1,2],[3]]

真的要找个时间补补循环了

image

网上大神这样解释

解释

  • 整体思路应该不难理解。外层的 i 用于确定截取的起始点。内层的 j 就是在 ii + size之间,读出每一个元素,并存储到 temp 中。每存好一个片段 (即内层循环结束),就把 temp保存到 result
  • 这个思路的关键在于选对 ij 的初始值以及循环过程中增值。既然我们需要实现每 size个元素为一个片段,那么我们肯定需要确定每次截取的起点和终点
  • 我们用 i 来表示截取的起点,那么不难得出 i 的初始值为 0。增值应该为 size。跳出条件也很简单,只要 i < arr.length,我们就可以一直执行
  • j 来选取范围中的元素,因此 j 的初始值应该就为 i (注意,这个 i 是会变化的)。至于 j 的结束值,那么应该为 i + size。因为我们需要截取的是从 ii + size 的元素。j的增值显然应该为 j++,因为我们需要获取这个范围之内的所有元素
  • 既然我们设置了 j 是从 ii + size,那么就需要处理 i + size 超出数组长度的情况。简单考虑下这个例子,传入数组 [1, 2, 3, 4, 5]size4,那么我们应该得到 [[1, 2, 3, 4], [5]]。当 i 为 0 的时候没有问题,但当第二次循环,即 i 为 4 的时候,这时 j 也为 4。而内层循环跳出条件,i + size 为 8,显然超出了原数组的长度。如果我们读取 arr[6],会得到 undefined,显然我们不想把这个结果放进 temp
  • 那么如何判断呢?你可能第一反应是用 if (arr[j]) 来判断。可以先试试,结果是通不过测试的。原因在于 JavaScript 的隐式类型转换,if() 中的内容会被转换成 Boolean,相当于执行的是 if(Boolean(arr[j])) 或者说 if(!!arr[j])。那么如果 arr[j] 是 0,就也会返回 false。但其实,0 在数组中肯定是允许的情况,我们不应该把它排除掉
  • 因此,这里我们只需要简单地判断 j 是否超出了 arr.length 即可。也就有了上面的代码

Slasher Flick

打不死的小强!

返回一个数组被截断n个元素后还剩余的元素,截断从索引0开始。

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function slasher(arr, howMany) {
  // it doesn't always pay to be first
  arr.splice(0,howMany);
  return arr;
}

slasher([1, 2, 3], 2);

这题挺简单的,arr.splice(0,howMany) 就是删掉 0 到 howMany 的元素。

Mutations

蛤蟆可以吃队友,也可以吃对手。

如果数组第一个字符串元素包含了第二个字符串元素的所有字符,函数返回true。

举例,["hello", "Hello"]应该返回true,因为在忽略大小写的情况下,第二个字符串的所有字符都可以在第一个字符串找到。

["hello", "hey"]应该返回false,因为字符串"hello"并不包含字符"y"。

["Alien", "line"]应该返回true,因为"line"中所有字符都可以在"Alien"找到。

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

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;
}

mutation(["hello", "hey"]);

这一道题要这样想先设置 arr 的第一个元素为 a ,第二的元素为 b 。并用 toLowerCase() 变成小写。

把数组 b 的一个一个元素和数组 a 匹配,如果没有匹配到该值,返回 -1,返回 false ,反则返回 turn

还是要多看 str.indexOf();

Falsy Bouncer

真假美猴王!

删除数组中的所有假值。

在JavaScript中,假值有falsenull0""undefinedNaN

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function bouncer(arr) {
  // Don't show a false ID to this bouncer.
  var result=[];
  for (var i=0;i<arr.length;i++) {
    if (Boolean(arr[i])) {
      result.push(arr[i]);
    }
  }
  return result;
}

bouncer([7, "ate", "", false, 9]);

result 设为一个空的数组

for 循环每个元素

boolean 不为假值就会加到数组 result

得出一个没有假值的数组。

Seek and Destroy

金克斯的迫击炮!

实现一个摧毁(destroyer)函数,第一个参数是待摧毁的数组,其余的参数是待摧毁的值。

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

我的解法:

function destroyer(arr) {
  // Remove all the values
  var arrDel=[];
  for (var i=1;i<arguments.length;i++) {
    arrDel.push(arguments[i]);
  }
  return arr.filter(function(val) {
    return arrDel.indexOf(val)<0;
  });
}

destroyer([1, 2, 3, 1, 2, 3], 2, 3);

这题是我觉得最难的一题了,刚开始一点头绪都没有,一步一步分析

var arrDel=[]; 先建立一个空数组

for (var i=1; 这个是跳过代删元素 [1, 2, 3, 1, 2, 3]

i<arguments.length;i++ 创建一个类似列表的东西 [[1, 2, 3, 1, 2, 3], 2, 3] ,因为跳过了代删元素,所以只会在 2,3 循环

2,3 加到 arrDel 数组中

返回到 arr.filter(function(val) 进行删除值,而且要通过 arrDel.indexOf(val)<0; 的验证,比如:

function(2) {
    return arrDel.indexOf(2)<0;
  }

arrDel.indexOf(2) 这一段是返回 4 的,所以成立

经过验证,2,3 是要删除的数字,删掉后返回 [1,1]

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

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

function where(arr, num) {
  // Find my place in this sorted array.
  arr.push(num);
  arr.sort(function(a,b){
             return a - b;
  });
  return arr.indexOf(num);
}

where([40, 60], 50);

先把num 加到数组

arr.sort() 把数组里的元素从小到大排列

arr.indexOf() 获得元素的索引值

function(a,b){
             return a - b;
  }

JavaScript 高级程序设计P94

由于比较函数通过返回一个小于零、等于零或大于零的值来影响排序结果,因此减法操作就可以适当的处理这些情况。

Caesars Cipher

让上帝的归上帝,凯撒的归凯撒。

下面我们来介绍风靡全球的凯撒密码Caesar cipher,又叫移位密码。

移位密码也就是密码中的字母会按照指定的数量来做移位。

一个常见的案例就是ROT13密码,字母会移位13个位置。由'A' ↔ 'N', 'B' ↔ 'O',以此类推。

写一个ROT13函数,实现输入加密字符串,输出解密字符串。

所有的字母都是大写,不要转化任何非字母形式的字符(例如:空格,标点符号),遇到这些特殊字符,跳过它们。

当你完成不了挑战的时候,记得开大招'Read-Search-Ask'。

这是一些对你有帮助的资源:

function rot13(str) { // LBH QVQ VG!
  var result="";
  for (var i=0;i<str.length;i++) {
    var currentCode=str[i].charCodeAt();
    if (currentCode>90||currentCode<65) {
      result += String.fromCharCode(currentCode);
    } else if (currentCode < 78) {
      result += String.fromCharCode(currentCode + 13);
    } else {
      result += String.fromCharCode(currentCode - 13);
    }
  }
  return result;
}

// Change the inputs below to test
rot13("SERR PBQR PNZC");

这里要先知道什么是 ASCII 码,A 到 M 的 ASCII 码是 65 到 77,N 到 Z 的 ASCII 码是 78 到 90

String.prototype.charCodeAt() 方法返回0到65535之间的整数,表示给定索引处的UTF-16代码单元 (在 Unicode 编码单元表示一个单一的 UTF-16 编码单元的情况下,UTF-16 编码单元匹配 Unicode 编码单元。但在——例如 Unicode 编码单元 > 0x10000 的这种——不能被一个 UTF-16 编码单元单独表示的情况下,只能匹配 Unicode 代理对的第一个编码单元) 。如果你想要整个代码点的值,使用 codePointAt()。

举个栗子:

下例返回 65,即 A 的 Unicode 值:

"ABC".charCodeAt(0) // returns 65

String.fromCharCode() 静态 String.fromCharCode() 方法返回使用指定的Unicode值序列创建的字符串。

举个栗子:

下例返回字符串 "ABC":

String.fromCharCode(65,66,67)

只要理解了这些其实这些算法也没有想象中那么难,不过我觉得还是要打好基础才行,不说了,先去看一遍 JavaScript 高级程序设计吧。

(完)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容