Free Code Camp 十六道JS基本算法题

记录一下,FCC通关过程中,基础算法,总共十五题。算是对些API的熟悉和对JS脚本结构一些熟悉。

1.Reverse a String--翻转字符串

要求:
先把字符串转化成数组,再借助数组的reverse方法翻转数组顺序,最后把数组转化成字符串。
结果必须得是一个字符串


思路:

  1. 直接split()拆分成数组
  2. 使用reverse()翻转数组
  3. 通过join() 把数组拼成字符串。
function reverseString(str) {
   var newstr = str.split("");  
   newstr.reverse();               
   str = newstr.join("");         
   return str;
}
reverseString("hello");

值得注意的是,join()应该在参数中添加一个空字符创,标识直接连接。直接使用,则会使用默认,使用逗号“,”分隔。

写的复杂了些,后来参照了别人的写法,链式结构,优化了一下。

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

2.Factorialize a Number--计算一个整数的阶乘

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


思路:

  1. 计算阶乘,从1开始,声明变量初始值 为1和 变量阶乘总值
  2. 用for循环,遍历参数传入的数值长度,进行累计相乘。
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。

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


思路:

  1. 检查回文,需要对字符串进行处理。转换小写(toLowerCase())、正则表达式处理特殊字符,然后拆分为数组(split())。
  2. 拆分为数组后,翻转数组(reverse()),合拼为字符串(jion()).
  3. 把合拼成的字符串和传入的参数字符串进行对比判断。
function palindrome(str) {
  
  var movestr = str.replace( /\W+/g ,'');  //正则表达式筛选所有非单词字符,替换为空的字符串
      movestr = movestr.replace(/\_+/g,'');  //正则表达式筛选所有下划线字符,替换为空的字符串  
      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");

第一次按思路实现,虽然实现了,但是写得很丑,尝试进行优化,两个优化的思路:

其一:

function palindrome(str) {

  str = str.replace(/[^A-Za-z0-9]/g,'').toLowerCase();  //正则表达式直接索引匹配以A-Z、a-z、0-9字符串和数字开始的,字符串转换为小写
  for(var i=0;i

其二:

function palindrome(str) {

  var re = /[\W\s_]/gi;    // 转义字符\W,非单词字符和空白字符并且不区分大小写
  str = str.replace(re,"");
  return str.toLowerCase() === str.split("").reverse().join("").toLowerCase();
}
palindrome("eye");

主要还是正则表达式的处理,花去了许多时间。正则还是很弱,得加强。

4.Find the Longest Word in a String -- 找出最长单词

要求:

在句子中找出最长的单词,并返回它的长度。
函数的返回值应该是一个数字。


思路:

  1. 拆分句子,把字符串拆分为一段段字符串,句子间使用空格拆分(split(' ')),保存在数组中。
  2. 声明一个初始值,对数组进行遍历,初始值和每一段字符串的length长度比较,较大的就赋值给初始值。遍历后初始值可得到最大的值。
function findLongestWord(str) {
  var newstr =str.split(" ");  // 字符串拆分为数组,空格间隔
  var longWord = 0;  //设置初始最小值
  for(var i=0; ilongWord){
       longWord=newstr[i].length;
    } 
  }
  return longWord;
}
findLongestWord("The quick brown fox jumped over the lazy dog");

按思路来,总是写不够好,还是得优化一下:

function findLongestWord(str) {
    var arr=str.split(" ");  // 字符串拆分为数组,空格间隔
    arr=arr.map(function(item){// map方法匹配出数组中各个字符串的长度,返回字符创长度
        return item.length;
    }).sort(function(a,b){ // sort()函数方法由大到小按顺序排序数字,
        return b-a;
    });
  return arr[0]; //  返回第一个最大数字
}

5.Title Case a Sentence--句中单词首字母大写

要求:
句中单词首字母大写
确保字符串的每个单词首字母都大写,其余部分小写。
像'the'和'of'这样的连接符同理。


思路:

  1. 先拆分句子,单独修改每一段字符串的首字母为大写,其余为小写。
  2. 把大小写转化后的字符串,转化回句子。
function titleCase(str) {
  var str1=str.split(" ");//拆分字符串为数组
  var str2; 
  var newstr;
  for(var i=0; i < str1.length;i++){
   str2=str1[i].split("");  //循环数组str1单词,拆分至数组str2单字符
   str2[0] = str2[0].toUpperCase(); //数组str2单字符首字符大写
   for(var j=1;j < str2.length;j++){  //数组str2单字符其余字符小写
       str2[j] = str2[j].toLowerCase();
        }
    str1[i] = str2.join("");  //单字符数组合并为单词;
  }
  newstr = str1.join(" ");  //单词数组合并为字符串;
  return newstr;
}
titleCase("I'm a little tea pot");

嗯恩恩.....还是得优化一下,两个for循环,感觉写了一长串。

function titleCase(str) {
  //toLowerCase()全部转化为小写、split()拆分字符串为数组、map()方法返回一个新数组;
  var newstr=str.toLowerCase().split(" ").map(function(item){ 
    return item[0].toString().toUpperCase()+item.slice(1);
    //获取数组的第一个字母,转化为大写
    //然后加上后面的小写内容(slice()方法获取范围内容,1表示从第二个字母开始)
  }).join(" ");   //join()方法组合成字符串
  return newstr;
}
titleCase("I'm a little tea pot");

6. Return Largest Numbers in Arrays--找出多个数组中的最大数

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


思路:

  1. 多重数组,先把子数组进行处理。遍历大数组,先对每个子数组进行排序。
  2. 把每个排序后的子数组,最大的添加到新数组。
function largestOfFour(arr) {
  var newArr=[];
  for(var i=0;i

7. Confirm the Ending--检查字符串结尾

要求:

判断一个字符串(str)是否以指定的字符串(target)结尾。
如果是,返回true;如果不是,返回false。
提示:String.substr()


思路:

  1. 思路很简单,直接获取要对比结尾字符串的长度,然后在长字符串中,找到对应长度的结尾,进行对比。
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");

也可以用前面用到过的slice()方法,
slice(star,end), start负数表示从字符串末尾开始算,end为可选,结束标
比如:
var str=“abcd”;
var newstr=str.slice(-2)
newstr

优化了一下,感觉也还可以。

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--重复输出字符串

要求:
重复输出字符串 (重要的事情说3遍)
重复一个指定的字符串 num次,如果num是一个负数则返回一个空字符串。

--
思路:
1.思路挺清晰的,重复输出n次字符串,n为负数则返回空字符串;

function repeat(str, num) {
 var newstr =str;
if(num >= 0){
 for(var i=0;i

后面思考了一下,把多一个if判断可以省略掉。

function repeat(str, num) {
  var newStr='';
  for(var i=1;i<=num;i++){
      newStr+=str;  
  }
  return newStr;
}

9. Truncate a string--截断字符串

要求:
截断字符串
(用瑞兹来截断对面的退路)

如果字符串的长度比指定的参数num长,则把多余的部分用...来表示。
切记,插入到字符串尾部的三个点号也会计入字符串的长度。
但是,如果指定的参数num小于或等于3,则添加的三个点号不会计入字符串的长度。

提示:slice()


思路:

  1. 进行两步判断,判断字符串是否大于给定的数值,大于则进行下一步判断,小于则直接返回。
  2. 当判断字符串大于给定数值,则再进行判断是是否大于最小值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);

稍微简化了一下

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-- 分割数组,猴子吃香蕉

要求:
猴子吃香蕉, 分割数组
(猴子吃香蕉可是掰成好几段来吃哦)
把一个数组arr按照指定的数组大小size分割成若干个数组块。

例如: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()


思路:

  1. 把数组分块,就先把数组拆分成指定数组快,然后添加到一个新数组中。
function chunk(arr, size) {
  var newArr=[];
 for(var i=0; i

11.Slasher Flick-- 截断数组

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

提示:Array.slice()、Array.splice()


思路:

  1. 挺简单的,主要是熟悉使用api,这里使用两个api都可以实现。

用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--比较字符串

要求:

比较字符串
(蛤蟆可以吃队友,也可以吃对手)

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

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

["hello", "hey"]应该返回false,因为字符串"hello"并不包含字符"y"。
["Alien", "line"]应该返回true,因为"line"中所有字符都可以在"Alien"找到。

提示:indexOf()


思路:

  1. 好像没有什么思路,按照要求一步步写下来。

indexOf() 方法返回调用 String 对象中第一次出现的指定值的索引,开始在 fromIndex进行搜索。
如果未找到该值,则返回-1

function mutation(arr) {
  arr[0]=arr[0].toLowerCase();
  arr[1]=arr[1].toLowerCase();
  for(var i=0;i

13.Falsy Bouncer--过滤数组假值

要求:

过滤数组假值
(真假美猴王)
删除数组中的所有假值。

在JavaScript中,假值有false、null、0、""、undefined 和 NaN。

提示:Boolean Objects 、Array.filter()


思路:

  1. 通过Boolean判断是否为true值,如果符合,就返回到新数组。Array.fillter()就可以实现。
  arr = arr.filter(filterFalsy);
  function filterFalsy(item){
       return Boolean(item) === true;
  }
  return arr;
bouncer([7, "ate", "", false, 9]);

14.Seek and Destroy--摧毁数组

要求:
摧毁数组
金克斯的迫击炮!
实现一个摧毁(destroyer)函数,第一个参数是待摧毁的数组,其余的参数是待摧毁的值。

提示:Arguments object 、Array.filter()Array.filter()


思路:

  1. 通过arguments 判断出有参数个数,然后作为循环条件
  2. Array.filter()筛选掉传进来的参数,把剩下的返回。
function destroyer(arr) {
  var arg =arguments;
  for(var i =1;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。

提示:sort()


思路:

  1. 先把要添加的数字push到数组中,然后用sort()再进行排序,然后用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--凯撒密码

要求:
凯撒密码

(让上帝的归上帝,凯撒的归凯撒)
下面我们来介绍风靡全球的凯撒密码Caesar cipher,又叫移位密码。
移位密码也就是密码中的字母会按照指定的数量来做移位。
一个常见的案例就是ROT13密码,字母会移位13个位置。由'A' ↔ 'N', 'B' ↔ 'O',以此类推。
写一个ROT13函数,实现输入加密字符串,输出解密字符串。
所有的字母都是大写,不要转化任何非字母形式的字符(例如:空格,标点符号),遇到这些特殊字符,跳过它们。

提示:charCodeAt() 、String.fromCharCode()

思路:

  1. ROT13的思路入手,先把传入字符串参数的每个字符拆分成Unicode,保存在一个数组中。
  2. 对这个数组进行处理,处于大写字母的Unicode码区间是65~90,遍历数组,不符合这个范围的直接返回。
  3. 符合范围的,进行ROT13的规则进行处理,每一个Unicode码值加上13,超出范围后,重头开始。

写出来的第一版:

function rot13(str) {
    var arr=[];
    var arr2=[];
    for(var i =0;i90){
            return x;
        } 
        else{
            if(x+13>90){
                return x+13-26;
            }
            else{
                return x+13;
            }
        }
    });
    
    for(var j = 0; j

进行优化后:

function rot13(str) {
  
  var arr =[];
  
  for(var i=0;i90){
          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"); 

完成啦。过完这十六道很基础题,学到了不少东西。

你可能感兴趣的:(Free Code Camp 十六道JS基本算法题)