FreeCodeCamp( FCC)前端工程师 中级算法练习 分析与解答

说在前面

这是要一篇非常简单的新手能看懂的文章,希望你喜欢。由于在 freecodecamp 中貌似!?无法使用 ES6 的某些语法,未测试具体。所以基本上用古老?!ES5,4写成,谢谢。在写本博文前没有参考过别人的做法,纯手打,我的方法肯定不是最好,只是以我自己喜欢的方式在写而已。

纯原创,转载请联系作者https//:wusuai1995@qq.comgivingwu@gmail.com

  • freecodecamp China
  • 不明白API参考MDN给出的解释
  • 个别题目没有判断函数参数及其类型,仅通过了Run tests
  • 如果你最近在写微信小程序蓝牙的话请参考wx-bluetooth
  • 有疑惑请留言

开始

Sum All Numbers in a Range

  1. 先对传入数组升序排列,拿到 [min, max]
  2. 然后 generateArr 成一个 [min, min+1, min+2, ..., max]
  3. Array.prototype.reduce 方法从左至右求和
function sumAll(arr) {
  if (!Array.isArray(arr) || !arr || !arr.length) return;
  arr = arr.sort(function(a, b){ return a-b;});
  arr = generateArr(arr[0], arr[1]);
  console.log(arr);

  return arr.reduce(function(accu, curr){
    return accu += curr;
  });
}

function generateArr(min, max) {
  var arr = [];
  while (min <= max) {
    arr.push(min);
    min++;
  }

  return arr;
}

Diff Two Arrays

  1. 合并两个数组成一个数组
  2. 通过一个 obj 缓存数组中每项的出现次数
  3. 返回 obj[arr[i]] 仅出现一次的项组成的数组
function diff(arr1, arr2) {
  if (!Array.isArray(arr1) || !Array.isArray(arr2)) return;
  var newArr = arr1.concat(arr2);

  return unique(newArr);
}

function unique(arr) {
  var a = [], i, l, item, key, obj = {};

  for (i = 0, l = arr.length; i < l; i++) {
    item = arr[i];
    if (obj[item] === undefined) {
      obj[item] = [item];
    } else {
      obj[item].push(item);
    }
  }

  console.log(arr, obj);

  for (key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (obj[key].length === 1){
        a = a.concat(obj[key]);
      }
    }
  }

  return a;
}

Roman Numeral Converter

  • 先把每个数所对应的阿拉伯数字和罗马数字取出来并一一对应
var RomanNumArr = [1000, 900, 500,  400, 100,  90,   50,   40,  10,   9,   5,    4,   1],
    RomanNumStrArr = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
  • 然后对给出的数进行 倒推求余 的推算并返回对应数字数组,比如139 = [100 + 39] = [100 + 3 * 10 + 9] = [100, 10, 10, 10, 9]
function getSeparatedRomanNumArr (num, arr) {
  arr = arr || [];

  for (var i = 0, l = RomanNumArr.length; i < l; i++) {
    var curr = RomanNumArr[i], next, int;

    if (num >= curr) {
      if (num % curr === 0) {
        return pushNumByTimes2Arr(curr, num / curr, arr);
      } else {
        next = num % curr;
        int = num - next;

        return getSeparatedRomanNumArr(next, pushNumByTimes2Arr(curr, int / curr, arr));
      }
    }
  }
}

function pushNumByTimes2Arr(num, times, arr) {
  while (times) {
    arr.push(num);
    times--;
  }

  return arr;
}
  • 将每个阿拉伯数字对上罗马数字,然后对返回的数组进行 Array.prototype.join 即可,例如上面例子139 = [100, 10, 10, 10, 9] = ['C', 'X', 'X', 'X', 'IX'].join('') = 'CXXXIX'
function convert(num) {
  if (!num || 'number' !== typeof +num) throw new TypeError();
  var romanNumArr = getSeparatedRomanNumArr(num);

  return romanNumArr.map(function(item){
    return RomanNumStrArr[RomanNumArr.indexOf(item)];
  }).join('');
}

Where art thou

  1. for loop取出collection中的每个对象的keys然后与source对象的keys进行比对通过函数getSameItems
  2. 将当前 collection[i]key 的与 sameKeys 进行比对,如果全部全等就 match 反正 false
function where(collection, source) {
  var arr = [], sourceKeys = Object.keys(source), obj, key, objKeys,
      sameKeys, i, l = collection.length, j, k, matched;

  for (i = 0; i < l; i++) {
    obj = collection[i];
    objKeys = Object.keys(obj);

    if (objKeys.length < sourceKeys.length) continue;
    sameKeys = getSameItems(sourceKeys, objKeys);
 
    if (sameKeys.length < sourceKeys.length) continue;
    matched = true;

    if (sameKeys && sameKeys.length) {
      for (j = 0, k = sameKeys.length; j < k; j++) {
        key = sameKeys[j];

        if (obj[key] !== source[key]) {
          matched = false;
        }
      }
    }

    if (matched) arr.push(obj);
  }

  return arr;
}

function getSameItems (arr1, arr2) {
  if (!arr1 || !arr1.length || !arr2 || !arr2.length) throw new TypeError();
  var arr = [];
  
  arr1.forEach(function(item){
    if (~arr2.indexOf(item)) {
      arr.push(item);
    }
  });
  
  return arr;
}

Search and Replace

function myReplace(str, before, after) {
  after = isUpperCase(before[0]) ? camelize(after) : after;
  str = str.replace(before, after);
  return str;
}

function camelize (str) {
  return str.slice(0, 1).toUpperCase() + str.slice(1, str.length);
}

function isUpperCase(s) {
  return s === s.toUpperCase();
}

Pig Latin

  1. 根据题意先写出元音数组vowels,然后分割字符串成数组并比对是否存在元音字符,如果有则立即返回该 index 位置,反之返回 undefined
  2. 如果 index === 0 则返回 str + 'way' 反之返回 str.slice(vowelIndex, str.length) + str.substr(0, vowelIndex) + 'ay';
function translate(str) {
  var vowelIndex = findVowelsIndex(str);
  str = vowelIndex === 0 ? str + 'way' : str.slice(vowelIndex, str.length) + str.substr(0, vowelIndex) + 'ay';

  return str;
}

function findVowelsIndex (str) {
  var vowels = ['a', 'e', 'i', 'o', 'u'];
  var strArr = str.split(''), i, l, index;
  
  for (i = 0, l = strArr.length; i < l; i++) {
    index = vowels.indexOf(strArr[i]);
    if (~index) {
      return i;
    }
  }
}

DNA Pairing

function pair(str) {
  var strArr = str.split(''), pairArr = [], pair, i, l;
  
  for (i = 0, l = strArr.length; i < l; i++) {
    switch(strArr[i]){
      case 'C':
        pair = 'G';
        break;
      case 'G':
        pair = 'C';
        break;
      case 'A':
        pair = 'T';
        break;
      case 'T':
        pair = 'A';
        break;
    }

    pairArr.push([strArr[i], pair]);
  }

  return pairArr;
}

Missing letters

  1. 比对给出的str的每个字符,并全部转换成
  2. 如果当前字符的 charCode 不等于 nextcharCode 则找到了该 迷失字符
function fearNotLetter(str) {
  var strArr, i, l, curr, next, noMissing = true;

  strArr = str.split('').map(function(word){
    return word.charCodeAt();
  });
  
  for (i = 0, l = strArr.length; i < l; i++) {
    curr = strArr[i];
    next = strArr[i + 1];

    console.log('curr:', curr, 'next:', next);

    if (i !== l - 1 && ++curr !== next) {
      str = String.fromCharCode(curr);
      noMissing = false;
      break;
    }
  }

  return noMissing ? undefined : str;
}

Boo who

function boo(bool) {
  // What is the new fad diet for ghost developers? The Boolean.
  if (typeof bool !== 'boolean') return false;

  return true;
}

Sorted Union

function unite(arr1, arr2, arr3) {
  return Array.prototype.reduce.call(arguments, function(accu, curr){
    console.log('accu:', accu);
    console.log('curr:', curr);
    curr = curr.filter(function(item){
      return !~accu.indexOf(item);
    });

    return accu.concat(curr);
  });
}

Convert HTML Entities

function convert(str) {
  var i, j, reg, chars = ['&', '<', '>', '"', "'"], strs = ['&amp;', '&lt;', '&gt;', '&quot;', '&apos;'];
  
  for (i = 0, l = chars.length; i < l; i++) {
    reg = new RegExp('\' + chars[i], 'gm');
    str = str.replace(reg, strs[i]);
  }

  return str;
}

Spinal Tap Case

function spinalCase(str) {
  // "It's such a fine line between stupid, and clever."
  // not, there is a comma still.
  // --David St. Hubbins
  var reg1 = /(s|\_)/g, reg2 = /([A-Z])/g;
  
  if (reg1.test(str)) {
    str = str.replace(reg1, '-');
  } else if (reg2.test(str)) {
    str = str.replace(reg2, '-$1');
  }
  
  str = str.toLowerCase();

  return str;
}

Sum All Odd Fibonacci Numbers

  1. 先拿到斐波那契中所有小于 num 的数
  2. 然后求该数组中所有奇数(odd)项的和
function sumFibs(num) {
  if (num <= 2) return num;
  var a = 1, b = 1, arr = [a, b], sum = 0, i, l;

  while (sum < num) {
    sum = a + b;
    if (sum <= num) arr.push(sum);
    a = b;
    b = sum;
  }

  console.log(arr);

  num = 0;

  for (i = 0, l = arr.length; i < l; i++) {
    if (arr[i] % 2 !== 0) {
      num += arr[i];
    }
  }
  
  return num;
}

Sum All Primes

  1. 先将所有数组转出来(抱歉这里用了ES6的新方法 Array.from,请参考MDN Array.from
  2. 判断每一个数是否是质数,通过函数isPrime
function sumPrimes(num) {
  return Array.from({length: num}).map(function(item, index){
    return ++index;
  }).filter(function(item){
    return isPrime(item);
  }).reduce(function(accu, curr){
    return accu += curr;
  });
}

function isPrime (num) {
  if (num <= 1) return;
  var i, l, prime = true;

  for (i = 2, l = num / 2 + 1; i < l; i++) {
    if (num % i === 0) {
      prime = false;
      break;
    }
  }

  return prime;
}

Smallest Common Multiple

PS: 这又是一个继罗马数字后不错的中级算法题

先上一波我用到的资料(即思路):

  1. 一个优秀的答案
  2. Git上老外的答案
  3. 如何求最小公倍数,我选用该帖子中 分解质因数法,所以我们得先求出所有的该区间中每个数的质因数数组,然后去重,最后乘上所有数的质因数
  4. 欧几里德算法
  5. 最大公约数
  6. 质因数分解

一个优秀的答案,同时向欧几里德表示respect

// *?!

Finders Keepers

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

Drop it

PS: 那一段卖队友也是很666,我表示赞同。但辅助会怎么想?

function drop(arr, func) {
  // Drop them elements.
  var n = arr.shift();

  if (n !== undefined) {
    if (!func(n)) {
      return drop(arr, func);
    } else {
      arr.unshift(n);
      return arr;
    }
  } else {
    return [];
  }

  return arr;
}

Steamroller

function steamroller(arr) {
  // I'm a steamroller, baby 
  var result = [], i, l;

  for(i = 0, l = arr.length; i < l; i++){
    if(Array.isArray(arr[i])){
      result = result.concat(steamroller(arr[i]));
    }else{
      result.push(arr[i]);
    }
  }

  return result;
}

Binary Agents

  1. 将二进制字符串参数通过空格切分为数组
  2. 将2进制转为10进制
  3. 通过 String.fromCharCode返回字符串
function binaryAgent(str) {
  return str.split(/s/g).map(function(s){
    return String.fromCharCode(parseInt(s, 2));
  }).join('');
}

Everything Be True

function every(collection, pre) {
  // Is everyone being true?
  return collection.every(function(item) {
    return item[pre];
  });
}

Arguments Optional

函数curry化参考JavaScript currying

function add(a, b) {
  var args = Array.prototype.slice.call(arguments, 0);

  if (typeof a !== 'number') return undefined;
  if (args.length < 2) {
    return function (b) {
      if (typeof b !== 'number') return undefined;
      args.push(b);

      return add.apply(this, args);
    };
  } else {
    if (typeof b !== 'number') return undefined;
  }

  return a + b;
}

结语

不算上我做题的时间,我就是复制自己写好的代码也花了一段时间。而且部分题目没有被 freeCodeCamp 记录了,又重新来一次,但只有前几道是。应该是间隔一段时间后,数据会被清掉而只记录是否完成状态。

表示这个 Smallest Common Multiple 我写的递归未过,所以不贴。

感谢上面贴出的所有引用连接,如果有任何引用存在问题,请联系作者立即下线。

观看容易,手打不易,且看且学习。

原文地址:https://www.cnblogs.com/givingwu/p/8400754.html