【FCC】javascript算法题闯关汇总(笔记)

算法题汇总:

Sum All Numbers in a Range

  • 题目要求:

    sumAll([4,1]) should return 10 because sum of all the numbers between 1 and 4 (both inclusive) is 10.

  • 思路:将传入的数组中的元素提取出来,用高斯求和公式计算和
    s u m = ( ( a 1 + a n ) ∗ n ) / 2 sum=((a1+an)*n)/2 sum=((a1+an)n)/2

  • 解法:

    function sumAll(arr) {
      let num1=arr[0];
      let num2=arr[1];
      let n=num1-num2>0?num1-num2+1:num2-num1+1;
      return (num1+num2)*n/2;
    }
    
    sumAll([1, 4]);
    
  • 注意点:项数处:两数的绝对值再加1


Diff Two Arrays

  • 题目:返回传入的两个数组中的不同元素

  • 思路:通过concat()方法将两个数组拼在一起,如果是两个数组当中的重复元素那么其第一次出现和最后一次出现的下标是不同的;反之,如果是不同元素,两个下标是一致的,可以利用js的indexOf()和lastIndexOf()实现这一设想。

    //语法:
    array.filter(function(currentValue,index,arr), thisValue)
    
  • 代码实现:

function diffArray(arr1, arr2) {
let tmp=arr1.concat(arr2);
return tmp.filter(function(n,i,arr){
  return arr.indexOf(n)===arr.lastIndexOf(n);
})
}

diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]);
  • 夸夸自己:感觉这种思维方式还挺新颖的,从数在数组当中当中的位置关系着手。


seek and destroy

  • 题目:传入数组和几个参数(具体不定,可以1,2,3……个),要求去掉数组中所有与给定元素相同的元素

  • 思路:

    • 关于传入参数不定:

      一开始我想到了之前学过的curried function(),但后来想想,其实(只是就我目前接触的为数不多的实例来看,将来这段话可能会修改),人家本质上也是要知道参数的个数并且据此制定返回规则。

    ​ 后来思考了一下为什么destroyer()只传进去了一个arr?终于意识到其实这整个就是一个数组,而待处理的数组是数组中的元素之一!

    这样一来问题就简单了,只需要把后续的需要处理的参数用新数组存起来,再用熟悉的filter()就解决了!

  • 解法:

    function destroyer(arr) {
    let delearr=[];
    for(let i=1;i<arguments.length;i++){
      delearr.push(arguments[i]);
    }
    return arr.filter(function(n,i,array){
      return delearr.indexOf(n)==-1;
    });
     
    }
    //闯关要求必须用 arguments 对象
    destroyer([1, 2, 3, 1, 2, 3], 2, 3);
    

Wherefore art thou

  • 题目要求:(直接看测试样例比较好懂)

    whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" })` should return `[{ first: "Tybalt", last: "Capulet" }]
    
  • 思路:与之前题目类似的地方:都是逐个查找;

    稍有不同的点:利用到了hash的性质。给定了value要找到对应的key

  • 解法:

    function whatIsInAName(collection, source) {
      let arr = [];
      // Only change code below this line
    let keys=Object.keys(source);
    //source 是values的集合,上一行代码获取它们相应的keys
    
    arr=collection.filter(function(item,index){
      return keys.every(function(key){
        return item.hasOwnProperty(key)&&item[key]===source[key]
      });
    });
      // Only change code above this line
      return arr;
    }
    
    whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });
    //hash
    

Spinal Tap Case

  • 题目描述:Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes.
  • 思路:我一开始拿到题目第一反应是敲下如下代码:
function spinalCase(str) {
  return str.toLowerCase().split(" ").join("-");
}

spinalCase('This Is Spinal Tap');
//toLowerCase and then split(" "),finally join("-")

但是不出意外测试集没有这么轻易放过我。

对于以下情况该方法无法处理:

spinalCase("thisIsSpinalTap") should return the string this-is-spinal-tap.

spinalCase("The_Andy_Griffith_Show") should return the string the-andy-griffith-show.

spinalCase("AllThe-small Things") should return the string all-the-small-things.

这说明我的分割标准还不能适用于普遍情况。

经过粗略观察这些需要被分割的字符都有以下特征之一(||):前有空格、下横线、首字母为大写。

想起之前做过一道类似的题,还特意强调不能用replace(),但是这里并没有强调喔,replace()在这题中会是一个更好的选择。(而且用split()再join()有一个问题就是一次只能传一个参数)。字符串的转换处理问题,当要处理的情况比较复杂的时候,正则表达式应该是首选!

  • 题解:

    function spinalCase(str) {
    
     return str.replace(/\s|_/g,'-').replace(/([a-z])([A-Z])/g,'$1-$2').toLowerCase();
    }
     
    spinalCase('thisIsSpinalTap');
    
    
  • 最后的一点小思考:这道题也让我想到了 形式语言与自动机 。


Pig Latin

  • 题目简介:

    • 给定一个字符串,如果是以元音开头,仅在其后加上“way:
    • 如果是以辅音开头,将遇到元音前的一个(或一串)字符移到字符串后面,并加上“ay”
  • 思路:用正则表达式,再利用字符串拼接的方法(concat())

  • 题解:

    function translatePigLatin(str) {
      let goalconsonant=/^[^aeiou]+/;
      //第一个^表示匹配字符串的开始位置,($表示结束位置),中括号里的^表示除提到的字符外的其他字符,+表示匹配一个或多个字符(连续的)
      let strfrontconsonant=str.match(goalconsonant);
    return strfrontconsonant==null?str.concat("way"):str.replace(goalconsonant,"").concat(strfrontconsonant).concat("ay");
      }
    
    translatePigLatin("consonant");
    

search and replace

  • 题目简介:这题的要求就是魔改replace(),并且使被替换内容与待替换内容首字母大小写形式保持一致。(如待替换的首字母为大写,即使用于替换的是小写,也要换成大写;反之,若待替换的是小写,即使用于替换的是大写,也要换成小写

  • 思路:将传入的目标字符串看成字符数组,找到要替换的下标索引(indexOf()),分情况对首字母进行大小写转换。

  • 题解:

function myReplace(str, before, after) {
  var index=str.indexOf(before);
  if(str[index]===str[index].toUpperCase()){
    after=after.charAt(0).toUpperCase()+after.slice(1);
  }
  else{
    after=after.charAt(0).toLowerCase()+after.slice(1);//处理after首字母是大写而before的是小写的情况
  }
  str=str.replace(before,after);
  return str;
}

myReplace("A quick brown fox jumped over the lazy dog", "jumped", "leaped");

DNA pair

  • 题目简介、分析:利用DNA碱基A-T C-G的背景,将所给的字符串转换为二维数组,要求二维数组中的每个元素是一个配对后的结果。

例如:pairElement("TTGAG") should return [["T","A"],["T","A"],["G","C"],["A","T"],["G","C"]].

  • 思路:将字符串转换为字符数组,创建一个对象,把配对关系以对象属性的方式呈现,然后用map(),将原数组的相应内容替换掉。

  • 题解:

    function pairElement(str) {
      let pairs={
    A:"T",
    T:"A",
    G:"C",
    C:"G"
      };
    let arr=str.split("");
    arr=arr.map(x=>[x,pairs[x]]);
    
      return arr;
    }
    
    pairElement("GCG");
    

Missing letters

  • 题目介绍:给定一串按字母表顺序排列的字符,要求返回其中缺失的字母。

如:fearNotLetter("abce") should return the string d.

  • 思路:利用ASCII码

  • 题解:

    function fearNotLetter(str) {
     for(let i=0;i<str.length;i++){
       if((str.charCodeAt(0)+i)!==str.charCodeAt(i)){
    return String.fromCharCode(str.charCodeAt(i)-1);
       }
     }
      return undefined;
    }
    
    fearNotLetter("abce");
    

sorted union

  • 题目介绍:如:uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]) should return [1, 3, 2, 5, 4].

注意:实际传入的数组个数不确定

  • 题目分析:

    • 1、面向过程的的想法:

    如果是要打印输出,用队列,若当前元素与已在队列中的元素重合则不如队,否则入队,最后将所有元素出队打印。

​ 如果仅仅是要返回整个数组,用栈就行,依次将不在当前数组中的元素入栈,最后返回。本题使用栈

对于传入数组个数不确定的问题,使用…展开运算符接收

        - 2、面向对象的想法:一个操作 flat() ,使数组降维
Array.prototype.flat()
//flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回

//语法:var newArray = arr.flat([depth])

再使用 new Set(),对数组去重

  • 题解:

思路1:面向过程:

function uniteUnique(arr) {
  let args=[...arguments];//接收所有的数组(个数未知,用...)
  let goal=[];
for(let i=0;i<args.length;i++){
  for(let j=0;j<args[i].length;j++){
    if(!goal.includes(args[i][j])){
      goal.push(args[i][j]);
      //逐个判断元素是否已在里面,不在则入栈
    }
  }
}
  return goal;
}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);

思路2:面向对象:

function uniteUnique(...arr) {
  var tmparr=arr.flat();
  return [...new Set(tmparr)];
}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);

Convert HTML Entities

  • 题目:Convert the characters &, <, >, " (double quote), and ' (apostrophe), in a string to their corresponding HTML entities
  • 分析:本题完全可以用最简单的switch case 选择语句去完成替换(也可以建一个对象),只需要知道对应的符号要转换成什么内容,也就是HTML格式即可,具体记不清也没关系,可以从测试样例找。

以下是对应的内容:

"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&apos;"
  • 题解:
function convertHTML(str) {
  let tmp=str.split("");
for(let i=0;i<tmp.length;i++){
  switch(tmp[i]){
    case "&":
      tmp[i]="&amp;";
      break;

    case "<":
      tmp[i]="&lt;";
      break;

      case ">":
      tmp[i]="&gt;";
      break;

      case '"':
      tmp[i]="&quot;";
      break;

      case "'":
      tmp[i]="&apos;";
      break;
      
  }
}
tmp=tmp.join("");
  return tmp;
}

convertHTML("Dolce & Gabbana");

Sum All Odd Fibonacci Numbers

  • 题目介绍:function sumFibs(num),要求返回小于数值为num的斐波拉契数中奇数的和。

  • 设一个sum,如果某个数x符合x%2!=0,sum+=x,最后返回sum

  • 题解:

    function sumFibs(num) {
    let m=0,n=1,sum=0;
    while(n<=num){
      if(n%2!==0) sum += n;
    n+=m;
    m=n-m;//始终保持m是比n小一位的斐波拉契数
    }
      return sum;
    }
    
    sumFibs(4);
    

Sum All Primes

  • 题目介绍:求num以内的质数的和(初级题目)

  • 思路:遍历num以内的数:一层for循环;判断其是否是是质数:for循环至i (考虑到一些特殊情况,设成i/2反而不方便)

  • 题解:

    function sumPrimes(num) {
      let i,j,sum=0;
      for(i=2;i<=num;i++){
        for(j=2;j<=i;j++){
          if(i%j===0){//不是质数就跳出第二层for循环
            break;
          }
        }
        if(j===i){
            //在如果是因为在if条件中break的(合数)不会满足这个条件,能满足这个条件的都是把所有小于的数都找一遍而没有找到因子的(即质数)
          sum+=i;
        }
      }
      return sum;
    }
    
    sumPrimes(10);
    

smallest common multiple

  • 题目简介:求给定范围的一组连续自然数的最小公倍数

  • 思路:和以往写c语言练习题里面的给定两个数求最小公倍数不一样,这里给定的是一个数组,也可以理解为是一个范围内的数。

    • 首先要对数组进行升序排序,便于后续处理。
    • 其次,求两个数的最小公倍数的时候,是先找出其中一个的在两数乘积范围内的倍数,再依次比对该数在不在另一个数中。这个思路也可以被借鉴到求多个数中。 先把最小公倍数的范围上限找到(即所有数的乘积),再从最大的数的倍数找起,如果能同时满足是其余所有数的倍数,则返回。
  • 题解:

    function smallestCommons(arr) {
      let tmpcom=1;
      const [min,max]=arr.sort((a,b)=>a-b);
      //先对传入数据进行处理
      for(let i=min;i<=max;i++){
       tmpcom *=i;//找出公倍数的上限
      }
      const range=max-min+1;
      for(let multiple=max;multiple<=tmpcom;multiple+=max){
              //每次加都保证一定符合是最大的那个数的倍数,在此基础上也满足是其他数倍数的则返回
        let count=0;
        for(let i=min;i<=max;i++){
    
          if(multiple%i===0) count++;
        }
        if(count===range) return multiple;
      }
     
    }
    
    smallestCommons([1,5]);
    

drop it

  • 题目:没什么好说的,不符合要求的数就出队,返回操作后的数组

  • 题解:

    function dropElements(arr, func) {
      while(arr.length>0&&!func(arr[0]))
      arr.shift();
      return arr;
    }
    
    dropElements([1, 2, 3], function(n) {return n < 3; });
    

    Steamroller

  • 题目简介:要求使用除flat()以外的方法实现对数组的扁平化操作

  • 思路:新建一个数组,如果传入数组的第i号元素不是数组而是单个值,元素入栈;若仍是一个数组,用递归的方法将其处理直至其为元素。用到函数式编程的写法

  • 题解:

    function steamrollArray(val,flatarr=[]) {
      //return arr.flat(Infinity);
    val.forEach(item=>{
      if(Array.isArray(item)) steamrollArray(item,flatarr);
      else flatarr.push(item);
    });
      return flatarr;
    }
    
    steamrollArray([1, [2], [3, [[4]]]]);
    

Binary Agents

  • 题目简介:将二进制码译为英文,给定输入中 字符用空格隔开。

输入样例如:

binaryAgent("01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001") should return the string I love FreeCodeCamp!
  • 思路:先将题目所给的二进制码(字符形式)转换为二进制整数 :parseInt(); 再将其转换为字符编码(String.fromCharCode())
  • 题解:
function binaryAgent(str) {
  let arr=str.split(" ");
  let goalarr=[];
  for(let i=0;i<arr.length;i++){
    goalarr.push(String.fromCharCode(parseInt(arr[i],2)));
  }
  
  return goalarr.join("");
}

binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");

Everything Be True

  • 题目简介:如标题

具体测试样例如:
t r u t h C h e c k ( [ " u s e r " : " T i n k y − W i n k y " , " s e x " : " m a l e " , " u s e r " : " D i p s y " , " s e x " : " m a l e " , " u s e r " : " L a a − L a a " , " s e x " : " f e m a l e " , " u s e r " : " P o " , " s e x " : " f e m a l e " ] , " s e x " ) s h o u l d r e t u r n t r u e . truthCheck([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}, {"user": "Laa-Laa", "sex": "female"}, {"user": "Po", "sex": "female"}], "sex") should return true. truthCheck(["user":"TinkyWinky","sex":"male","user":"Dipsy","sex":"male","user":"LaaLaa","sex":"female","user":"Po","sex":"female"],"sex")shouldreturntrue.

  • 题解
function truthCheck(collection, pre) {
  return collection.every(obj=>obj[pre]);
}

truthCheck([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}, {"user": "Laa-Laa", "sex": "female"}, {"user": "Po", "sex": "female"}], "sex");

Arguments Optional

  • 题目要求:

    • 基本要求:实现两数相加,如
      a d d T o g e t h e r ( 2 , 3 ) s h o u l d r e t u r n 5 addTogether(2, 3) should return 5 addTogether(2,3)shouldreturn5

    • 附加要求:对其他情况进行处理。如,传入的参数有不是数的,返回undefined;像传入了
      a d d T o g e t h e r ( 5 ) ( 7 ) addTogether(5)(7) addTogether(5)(7)

这样的参数的,在函数内部其实应该返回一个函数,然后再调用这个函数使得最终返回两者相加的数值,如这个例子中的12;

  • 题解:

    function addTogether() {
    const [first,second]=arguments;
    if(typeof(first)!=="number") return undefined;
    if(second===undefined)
    return (second)=>addTogether(first,second);
    if(typeof(second)!=="number") return undefined;
    
    
      else return first+second;
    }
    
    addTogether(2,3);
    

Make a Person

  • 题目要求:考察avascript面向对象思想中的类的创建。

  • 题解:

    const Person = function(firstAndLast) {
      // Only change code below this line
      // Complete the method below and implement the others similarly
      var fullname=firstAndLast;
    
      this.getFullName = function() {
        return fullname;
      };
    this.getFirstName=function(){
    return fullname.split(" ")[0];
    };
      
    this.getLastName=function(){
    return fullname.split(" ")[1];
    };
    
    this.setFirstName=function(name){
      fullname=name+" "+fullname.split(" ")[1];
    };
    
    this.setLastName=function(name){
      fullname=fullname.split(" ")[0]+" "+name;
    };
    
    this.setFullName=function(name){
      fullname=name;
    };
    
    
    };
    
    const bob = new Person('Bob Ross');
    bob.getFullName();
    

最后一题不太想写

结语

这个笔记的时间跨度有点长,所以前后记录风格可能不太一致。同时,思路主要参考FCC的提示区/CSDN/知乎/简书。
感谢能看到这里的小伙伴,也希望这个对你的解题有帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值