FCC-intermediate-algorithm

Basic Algorithm——JavaScript

Happy Coding.
本文为 FreeCodeCamp 中前端的二十一道基础算法题及解答。

Sum All Numbers in a Range


我们会传递给你一个包含两个数字的数组。返回这两个数字和它们之间所有数字的和。

最小的数字并非总在最前面。

function sumAll(arr) {
  var max = Math.max.apply(null, arr),
      min = Math.min.apply(null, arr);
  var sum = 0;
  for(; min <= max; min++)
    sum += min;
  return sum;
}

sumAll([5, 10]);// 45
sumAll([1, 4]);// 10

Diff Two Arrays


比较两个数组,然后返回一个新数组,该数组的元素为两个给定数组中所有独有的数组元素。换言之,返回两个数组的差异。

function diff(arr1, arr2) {
  var newArr = [];
  var obj = {};
  arr1 = arr1.concat(arr2);
  arr1.map(function(item){
    obj[item] = ++obj[item] || 1;
  });
  arr1.forEach(function(item){
    if(obj[item] <= 1){
      newArr.push(item);
    }
  });

  return newArr;
}

diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);// [4]

Roman Numeral Converter


将给定的数字转换成罗马数字。

所有返回的 罗马数字 都应该是大写形式。

function convert(num) {
 var nums = [1000,900,500,400,100,90,50,40,10,9,5,4,1];
  var romans =["m","cm","d","cd","c","xc","l","xl","x","ix","v","iv","i"];
  var str = '';
  nums.forEach(function(item,index,array){
    while(num >= item){
      str += romans[index];
      num -= item;
    }
  });

 return str.toUpperCase();
}

convert(29);// XXIX

Where art thou


写一个 function,它遍历一个对象数组(第一个参数)并返回一个包含相匹配的属性-值对(第二个参数)的所有对象的数组。如果返回的数组中包含 source 对象的属性-值对,那么此对象的每一个属性-值对都必须存在于 collection 的对象中。

例如,如果第一个参数是 [{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }],第二个参数是 { last: "Capulet" },那么你必须从数组(第一个参数)返回其中的第三个对象,因为它包含了作为第二个参数传递的属性-值对。

function where(collection, source) {
  var arr = [];
  var flag = false;

  collection.map(function(item){
    for(var o in source){
      if(item[o] !== source[o]) {
        flag = false;
        break;
      } else {
        flag = true;
      }
    }
    if(flag){
      arr.push(item);
    }

  });
  return arr;
}

where([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });
// [{ first: "Tybalt", last: "Capulet" }]

Search and Replace


使用给定的参数对句子执行一次查找和替换,然后返回新句子。

第一个参数是将要对其执行查找和替换的句子。

第二个参数是将被替换掉的单词(替换前的单词)。

第三个参数用于替换第二个参数(替换后的单词)。

注意:替换时保持原单词的大小写。例如,如果你想用单词 “dog” 替换单词 “Book” ,你应该替换成 “Dog”。

function myReplace(str, before, after) {
  return before !== before.toLowerCase() ? 
    str.replace(before, after.slice(0, 1).toUpperCase() + after.slice(1)) : str.replace(before, after);
}

myReplace("He is Sleeping on the couch", "Sleeping", "sitting");// "He is Sitting on the couch"

Pig Latin


把指定的字符串翻译成 pig latin。

Pig Latin 把一个英文单词的第一个辅音或辅音丛(consonant cluster)移到词尾,然后加上后缀 “ay”。

如果单词以元音开始,你只需要在词尾添加 “way” 就可以了。

注:辅音丛即使截取第一个到’a’,’e’,’i’,’o’,’u’的字符串。

function translate(str) {
  var i = 0;
  while(i < str.length){
    if("aeiou".indexOf(str.slice(i, i + 1)) !== -1)
      break;
    i++;
  }
  return "aeiou".indexOf(str.slice(0, 1)) === -1 ? str.slice(i) + str.slice(0, i) + 'ay' : str + 'way';
}

translate("glove");// "oveglay"

DNA Pairing


DNA 链缺少配对的碱基。依据每一个碱基,为其找到配对的碱基,然后将结果作为第二个数组返回。

Base pairs(碱基对) 是一对 AT 和 CG,为给定的字母匹配缺失的碱基。

在每一个数组中将给定的字母作为第一个碱基返回。

例如,对于输入的 GCG,相应地返回 [[“G”, “C”], [“C”,”G”],[“G”, “C”]]

字母和与之配对的字母在一个数组内,然后所有数组再被组织起来封装进一个数组。

function pair(str) {
  var arr = [];
  str.split('').map(function(item){
    switch(item){
      case 'T':
        arr.push(['T', 'A']);
        break;
      case 'A':
        arr.push(['A', 'T']);
        break;
      case 'G':
        arr.push(['G', 'C']);
        break;
      case 'C':
        arr.push(['C', 'G']);
    }
  });
  return arr;
}

pair("GCG"); // function pair(str) {
  var arr = [];
  str.split('').map(function(item){
    switch(item){
      case 'T':
        arr.push(['T', 'A']);
        break;
      case 'A':
        arr.push(['A', 'T']);
        break;
      case 'G':
        arr.push(['G', 'C']);
        break;
      case 'C':
        arr.push(['C', 'G']);
    }
  });
  return arr;
}

pair("TTGAG");// [["T","A"],["T","A"],["G","C"],["A","T"],["G","C"]]

Missing letters


从传递进来的字母序列中找到缺失的字母并返回它。

如果所有字母都在序列中,返回 undefined.

function fearNotLetter(str) {
  var charArr = str.split('').map(function(item){
    return item.charCodeAt();
  });
  for(var i = 0; i < charArr.length - 1; i++){
    if(charArr[i + 1] - charArr[i] > 1){
      return String.fromCharCode(charArr[i + 1] - 1);
    }
  }
  return undefined;
}

fearNotLetter("abce");

Boo who


检查一个值是否是基本布尔类型,并返回 true 或 false。

基本布尔类型即 true 和 false。

function boo(bool) {
  return typeof bool === 'boolean';
}

Sorted Union


写一个 function,传入两个或两个以上的数组,返回一个以给定的原始数组排序的不包含重复值的新数组。

换句话说,所有数组中的所有值都应该以原始顺序被包含在内,但是在最终的数组中不包含重复值。

非重复的数字应该以它们原始的顺序排序,但最终的数组不应该以数字顺序排序。

function unite(arr1, arr2, arr3) {
  var args = Array.prototype.slice.call(arguments, 0);
  var newArr = [], arr1 = [];
  for(var i = 0; i < args.length; i++){
    newArr = newArr.concat(args[i]);
  }
  newArr.forEach(function(item){
    if(arr1.indexOf(item) === -1) arr1.push(item);
  });
  return arr1;
}

unite([1, 3, 2], [5, 2, 1, 4], [2, 1]);// [1, 3, 2, 5, 4]

Convert HTML Entities


将字符串中的字符 &<>" (双引号), 以及 ' (单引号)转换为它们对应的 HTML 实体。

function convert(str) {
  return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&apos;').replace(/"/g,'&quot;');
}

convert("Dolce & Gabbana");// Dolce &amp; Gabbana

Spinal Tap Case


将字符串转换为 spinal case。Spinal case 是 all-lowercase-words-joined-by-dashes 这种形式的,也就是以连字符连接所有小写单词。

function spinalCase(str) {
  return str.replace(/\s|_/g,'-').replace(/([a-z])([A-Z])/g,'$1-$2').toLowerCase();
}

spinalCase('This Is Spinal Tap');// this-is-spinal-tap
spinalCase("The_Andy_Griffith_Show");// the-andy-griffith-show

Sum All Odd Fibonacci Numbers


给一个正整数num,返回小于或等于num的斐波纳契奇数之和。

斐波纳契数列中的前几个数字是 1、1、2、3、5 和 8,随后的每一个数字都是前两个数字之和。

例如,sumFibs(4)应该返回 5,因为斐波纳契数列中所有小于4的奇数是 1、1、3。

提示:此题不能用递归来实现斐波纳契数列。因为当num较大时,内存会溢出,推荐用数组来实现。

function sumFibs(num) {
  var fibs = [1, 1], sum = 0;
  if(num <= fibs.length) return 1;

  for(var i = 0; fibs[i] <= num; i++){
    fibs.push(fibs[fibs.length - 1] + fibs[fibs.length - 2]);
    if(fibs[i] % 2 === 1)
      sum += fibs[i];
  }
  return sum;
}

sumFibs(4000000);// 4613732

Sum All Primes


求小于等于给定数值的质数之和。

只有 1 和它本身两个约数的数叫质数。例如,2 是质数,因为它只能被 1 和 2 整除。1 不是质数,因为它只能被自身整除。

给定的数不一定是质数。

function sumPrimes(num) {
  var primes = [2, 3, 5];
  var sum = 10;
  for(var i = 6; i <= num; i++){
    if(i % 2 === 0 || i % 3 === 0 || i % 5 === 0) continue;
    for(var j = 2; j < i; j++){
      if(i % j === 0) break;
    }
    if(j >= i){
      primes.push(i);
      sum += i;
    }
  }
  return sum;
}

sumPrimes(977);// 73156。

Smallest Common Multiple


找出能被两个给定参数和它们之间的连续数字整除的最小公倍数。

范围是两个数字构成的数组,两个数字不一定按数字顺序排序。

例如对 1 和 3 —— 找出能被 1 和 3 和它们之间所有数字整除的最小公倍数。

function smallestCommons(arr) {
  arr = arr.sort(function(a, b){
    return a - b;
  });
  var mul = arr[0];
  for(var i = arr[0] + 1; i <= arr[1]; i++){
    mul *= i / gcd(i, mul);
  }
  return mul;
}
function gcd(m, n){
  if(m % n === 0) return n;
  return gcd(n, m % n);
}

smallestCommons([5, 1]);// 60
smallestCommons([1, 13]);// 360360

Finders Keepers


写一个 function,它遍历数组 arr,并返回数组中第一个满足 func 返回值的元素。举个例子,如果 arr[1, 2, 3]funcfunction(num) {return num === 2; },那么 find 的返回值应为 2

function find(arr, func) {
  return arr.filter(func)[0];
}

find([1, 2, 3, 4], function(num){ return num % 2 === 0; });// 2
find([1, 3, 5, 9], function(num) { return num % 2 === 0; });// undefined。

Drop it


队友该卖就卖,千万别舍不得。

当你的队伍被敌人包围时,你选择拯救谁、抛弃谁非常重要,如果选择错误就会造成团灭。

如果是AD或AP,优先拯救。

因为AD和AP是队伍输出的核心。

其次应该拯救打野。

因为打野死了对面就可以无所顾虑地打龙。

最后才是辅助或上单。

因为辅助和上单都是肉,死了也不会对团队造成毁灭性影响,该卖就卖。

但真实中的团战远比这要复杂,你的队伍很可能会被敌人分割成2个或3个部分。

当你救了一个重要的人时,很可能其他队友也会因此获救。

举个例子:

辅助和AD经常是在一起的,打野和中单在一起,上单经常一个人。

你救了AD,辅助也经常因此获救。

让我们来丢弃数组(arr)的元素,从左边开始,直到回调函数return true就停止。

第二个参数,func,是一个函数。用来测试数组的第一个元素,如果返回fasle,就从数组中抛出该元素(注意:此时数组已被改变),继续测试数组的第一个元素,如果返回fasle,继续抛出,直到返回true。

最后返回数组的剩余部分,如果没有剩余,就返回一个空数组。

function drop(arr, func) {
  // Drop them elements.
  var num = arr.indexOf(arr.filter(func)[0]);
  return num !== -1 ?  arr.slice(num) : [];
}

drop([1, 2, 3, 4], function(n) {return n >= 3;});// [3, 4]。
drop([0, 1, 0, 1], function(n) {return n === 1;});// 应该返回 [1, 0, 1]。
drop([1, 2, 3], function(n) {return n > 0;});// 应该返回 [1, 2, 3]。
drop([1, 2, 3, 4], function(n) {return n > 5;});// 应该返回 []。
drop([1, 2, 3, 7, 4], function(n) {return n > 3;});// 应该返回 [7, 4]。
drop([1, 2, 3, 9, 2], function(n) {return n > 2;});// 应该返回 [3, 9, 2]。

Steamroller


对嵌套的数组进行扁平化处理。你必须考虑到不同层级的嵌套。

function steamroller(arr, newArr) {
  newArr = newArr || [];
  for (var i = 0; i < arr.length; i++) {
    if (!Array.isArray(arr[i])) {
      newArr.push(arr[i]);
    } else {
      steamroller(arr[i],newArr);
    }       
  }
  return newArr;
}

steamroller([1, {}, [3, [[4]]]]);// [1, {}, 3, 4]

Binary Agents


传入二进制字符串,翻译成英语句子并返回。

二进制字符串是以空格分隔的。

function binaryAgent(str) {
  var newArr = str.split(' ').map(function(item){
    return parseInt(item, 2);
  });
  return String.fromCharCode.apply(null, newArr);
}

binaryAgent("01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111");// 应该返回 "Aren't bonfires fun!?"
binaryAgent("01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001");// 应该返回 "I love FreeCodeCamp!"

Everything Be True


所有的东西都是真的!

完善编辑器中的every函数,如果集合(collection)中的所有对象都存在对应的属性(pre),并且属性(pre)对应的值为真。函数返回ture。反之,返回false。

记住:你只能通过中括号来访问对象的变量属性(pre)。

function every(collection, pre) {
  return collection.every(function(item){
    return !!item[pre];
  });
}

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

Arguments Optional


创建一个计算两个参数之和的 function。如果只有一个参数,则返回一个 function,该 function 请求一个参数然后返回求和的结果。

例如,add(2, 3) 应该返回 5,而 add(2) 应该返回一个 function。

调用这个有一个参数的返回的 function,返回求和的结果:

var sumTwoAnd = add(2);

sumTwoAnd(3) 返回 5

如果两个参数都不是有效的数字,则返回 undefined。

function add() {
  var args = [].slice.apply(arguments);
  var flag = args.every(function(item){
    return typeof item === 'number';
  });
  if(!flag){
    return undefined;
  }
  if(args.length >= 2){
    return args.reduce(function(acc, curVal){
      return acc + curVal;
    });
  } else {
    return function(second){
      if(typeof second !== 'number') return undefined;
      return args[0] + second;
    };
  }
}

add(2, 3);// 5。
add(2)(3);// 5。
add("http://bit.ly/IqT6zt");// undefined。
add(2, "3");// undefined。
add(2)([3]);// undefined。
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值