FreeCodeCamp中级算法(更新中)

1.计算一个范围数字之和

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

sumAll([1, 4])应该返回 10。
sumAll([10, 5])应该返回 45。

这里可以用到 array.reduce()

太长了我就不粘了,点这里看详细介绍

总之就是会对数组中每个元素执行一次回调函数,累加可以用下面的代码

var total = [0, 1, 2, 3].reduce(function(a, b) {
    return a + b;
});
// total == 6

然后再找到哪个数大,哪个数小

var maxnum = Math.max(arr[0],arr[1]);
var minnum = Math.min(arr[0],arr[1]);

然后在他们之间循环push进新数组

for(var i = minnum + 1 ; i < maxnum; i++) {
    arr.push(i);
}

对新数组执行reduce就可以了

总体代码

function sumAll(arr) {
  var maxnum = Math.max(arr[0],arr[1]);
  var minnum = Math.min(arr[0],arr[1]);
  for(var i = minnum + 1 ; i < maxnum; i++) {
    arr.push(i);
  }
  return arr.reduce(function(a,b) {
    return a+b;
  });
}

sumAll([1, 4]);

2.找两个数组的差异

比较两个数组,然后返回一个新数组,该数组的元素为两个给定数组中所有独有的数组元素。换言之,返回两个数组的差异。
[1, 2, 3, 5], [1, 2, 3, 4, 5]应该返回 [4]。
[1, "calf", 3, "piglet"], [1, "calf", 3, 4]应该返回 ["piglet", 4]。

这个很简单,先找数组一中不被数组二包含的元素,再找出数组二中不被一包含的元素,push进新数组。

判断一个数组是不是包含某个元素,可以用arr.indexOf(),该方法会返回元素在数组中的位置,如果数组中没有这个元素,则返回 -1 ,所以可以用这个方法判断一个数组是不是包含某个元素

function diff(arr1, arr2) {
  var newArr = [];
  for(var i = 0; i < arr1.length; i++) {
    if (arr2.indexOf(arr1[i]) < 0) {
      newArr.push(arr1[i]);
    }
  }
  for(var j = 0; j < arr2.length; j++) {
    if(arr1.indexOf(arr2[j]) < 0) {
      newArr.push(arr2[j]);
    }
  }
  return newArr;
}

diff([1, "calf", 3, "piglet"], [7, "filly"]);

3.将给定的数字转换成罗马数字

convert(2)应该返回 "II"。
convert(29)应该返回 "XXIX"。
convert(798)应该返回 "DCCXCVIII"。
convert(3999)应该返回 "MMMCMXCIX"。

这一题我想了好久不会做,最后看的别人的解法,非常简洁,代码如下。

function convert(num) {
  var alb = [1000,900,500,400,100,90,50,40,10,9,5,4,1];
  var roma = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"];
  var roman = "";
  for(var i=0;i<alb.length;i++) {
    while(num>=alb[i]) {
      roman = roman + roma[i];
      num = num - alb[i];
    }
  }
  return roman;
}

convert(36);

4.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 sss = Object.keys(source);
  var rel = [];
  // What's in a name?
  for(var i=0; i<collection.length; i++) {
    for(var j=0; j<sss.length; j++) {
      if(collection[i][sss[j]] == source[sss[j]]) {
        rel.push(0);
      } else {
        rel.push(1);
      }
    }
    if (rel.indexOf(1)<0) {
        arr.push(collection[i]);
      } else{
        rel = [];
      }
  }
  return arr;
}

where([{ "a": 1, "b": 2 }, { "a": 1 }, { "a": 1, "b": 2, "c": 2 }], { "a": 1, "b": 2 });

这个我用的方法有点复杂,先用Object.keys()获取source里面所有可枚举属性的属性名并赋值给sss,这里如果source{ "a": 1, "b": 2 } ,那么Object.keys(source)会返回["a',"b"],然后进行两次遍历判断,为了确定数组每个元素的所有属性都与source相等先遍历collection,然后对每个collection遍历sss,如果collection[i][sss[j]属性的值等于source[sss[j]],就先给空数组push一个0,代表正确,否则push一个1,代表错误。如果这个数组不含有有1,代表这个元素里没有不和source相等的,那么就把这个collection[i]push进结果数组,否则只要含有1,就证明含有不等于source的,那么就不push,并且重置数组,准备对下一个collection[i]进行遍历。为了好理解我在纸上画了个图,(估计只有我自己能看清,要是有人看的话我再重新写)

5.查找与替换

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

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

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

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

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

function myReplace(str, before, after) {
  var afters = after.charAt(0);
  if (before.charAt(0).charCodeAt() < 91) {
    afters = afters.toUpperCase();
  }
  var newAfter = after.replace(after.charAt(0),afters);
  return str.replace( before, newAfter);
}

myReplace("Let us go to the store", "store", "mall");

主要还是String.replace() 问题在于大小写的判断,这里用str.charCodeAt() 查询字母在ASCII的编码,A-Z的编码为65-90,a-z的编码为97-122,所以可以加一个判断,如果before的首字母的ASCII编码小于91,既为大写,那么就把after的首字母toUpperCase(),然后利用str.replace()替换即可

6.儿童黑话

把一个英文单词的第一个辅音或辅音丛(consonant cluster)移到词尾,然后加上后缀 "ay"。
如果单词以元音开始,你只需要在词尾添加 "way" 就可以了。
translate("california")应该返回 "aliforniacay"。
translate("algorithm")应该返回 "algorithmway"。

由于我的英语不太好,分不清什么是辅从音,只好只包含了例子中的。

function translate(str) {
  var pig = ["a","e","i","o","u","A","E","I","O","U","g","G"];
  var first = str.charAt(0);
  if (pig.indexOf(first) < 0) {
    return str.substr(1,str.length-1)+str.charAt(0)+"ay";
  } else if(str.substr(0,2) == "gl") {
    return str.substr(2,str.length-1)+str.substr(0,2)+"ay";
  } else return str+ "way";
}

translate("glove");

思路:把所有需要替换的放到一个数组里,然后用str.charAt(0)获取字符串首字母,再用indexOf()检查首字母是否再需要替换的数组里,如果是,就对数组进行如下操作:

return str.substr(1,str.length-1)+str.charAt(0)+"ay"

然后再判断是否是辅音丛,因为辅音丛是两个字符,所以就substr(0,2)截取前两个字符去比较,如果满足做如下操作:

return str.substr(2,str.length-1)+str.substr(0,2)+"ay";

都不满足则返回字符串+way

7.DNA配对

DNA 链缺少配对的碱基。依据每一个碱基,为其找到配对的碱基,然后将结果作为第二个数组返回。
Base pairs(碱基对) 是一对 AT 和 CG,为给定的字母匹配缺失的碱基。
在每一个数组中将给定的字母作为第一个碱基返回。
例如,对于输入的 GCG,相应地返回 [["G", "C"], ["C","G"],["G", "C"]]
字母和与之配对的字母在一个数组内,然后所有数组再被组织起来封装进一个数组。
pair("ATCGA")应该返回 [["A","T"],["T","A"],["C","G"],["G","C"],["A","T"]]。

function pair(str) {
  var rel = [];
  var bp = {
    A: "T",
    T: "A",
    C: "G",
    G: "C"
  };
  var strarr = str.split("");
  for(var i = 0; i<strarr.length; i++) {
    rel[i] = [strarr[i]];
    rel[i].push(bp[strarr[i]]);
  }
  return rel;
}

pair("ATCGA");

思路:这个主要是封装进数组不太容易操作。
新建一个对象,里面keyvalue一一对应,y因为传入的是一个字符串,所以先用str.split("")分割并存为新数组,然后遍历该数组,每个值新建一个数组,再根据key去对象里找对应的value push进这个数组(小数组)就可以得到由几个小数组封装起来的数组了。

8.丢失的信

从传递进来的字母序列中找到缺失的字母并返回它。
如果所有字母都在序列中,返回 undefined。
fearNotLetter("abce")应该返回 "d"。

function fearNotLetter(str) {
  var arr = str.split("");
  var numarr = [];
  for(var i = 0; i<arr.length; i++) {
    numarr.push(arr[i].charCodeAt());
  }
  for(var j = numarr[0]; j<numarr.length+numarr[0]+1; j++) {
    if(numarr[j-numarr[0]] != j) {
        return String.fromCharCode(j);
    } else if (numarr[numarr.length-1] == j) {
      return undefined;
    }
  }
}

fearNotLetter("abce");

思路:将字符串分割后存到新数组,遍历该数组并把每个元素的索引push到数组2,这样就得到由索引组成的数组,一眼就能看出来哪里少了一个。。。(开个玩笑,计算机可看不出来)

然后对该索引组成的数组遍历,注意起始值设置为该数组的第一个元素,这样能保证遍历的时候 i 正好与索引一一对应,如果哪一个没对应住,就说明这里缺了一个嘛,此时就输出 i 对应的索引准没错,对应程序里就是这一堆,可能不是那么容易理解,关键点在于遍历的起始值,终止值要设置好

for(var j = numarr[0]; j<numarr.length+numarr[0]+1; j++) {
    if(numarr[j-numarr[0]] != j) {
        return String.fromCharCode(j);
    } else if (numarr[numarr.length-1] == j) {
      return undefined;
    }
  }

这里有个坑。。。开始的时候我写如果判断条件满足的话输出索引,否则输出undefined,乍一看没有错。但是这里是在遍历啊,敲黑板,第一个不满足判断条件直接就输出了好嘛。然后我就想,再判断是否全都对应太麻烦了,那如果只判断最后一个呢?是个好方法啊!因为如果前面不满足直接就return了,既然能遍历到最后一个,前面肯定没有漏啊,那这样我只需要比较一下最后一个是否满足条件就可以输出了嘛。

9.判断是否是布尔值

检查一个值是否是基本布尔类型,并返回 true 或 false。
基本布尔类型即 true 和 false。
boo(true)应该返回 true。
boo(false)应该返回 true。
boo([1, 2, 3])应该返回 false。
boo(1)应该返回 false。

这是一道送分题啊同学们

function boo(bool) {
  return Boolean(bool)===bool?true:false;
}

boo(null);

这里用到了条件操作符,非常好用,基本用法是:

//判断条件 ? 条件为真时的操作 : 条件为假时的操作

//如果Boolean(bool)===bool则返回true,否则返回false
return Boolean(bool)===bool?true:false;

这里要注意要用===来判断,因为==会转换类型,比如数字1会被转换为true而导致输出结果有误

10.Sorted Union

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

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

非重复的数字应该以它们原始的顺序排序,但最终的数组不应该以数字顺序排序。
unite([1, 3, 2], [5, 2, 1, 4], [2, 1])应该返回 [1, 3, 2, 5, 4]。
unite([1, 2, 3], [5, 2, 1])应该返回 [1, 2, 3, 5]。

题目不难,因为传入的参数不确定,所以我用了最笨的方法:暴力举穷。。其实可以用arguments的,以后再更新吧,今天有点懒。。

function unite(arr1, arr2, arr3,arr4) {
  for (var i = 0; i<arr2.length; i++) {
    if (arr1.indexOf(arr2[i]) < 0) {
      arr1.push(arr2[i]);
    }
  }
  if (arr3 !== undefined) {
    for (var j = 0; j<arr3.length; j++) {
      if (arr1.indexOf(arr3[j]) < 0) {
        arr1.push(arr3[j]);
      }
    }
  }
  if (arr4 !== undefined) {
    for (var k = 0; k<arr4.length; k++) {
      if (arr1.indexOf(arr4[k]) < 0) {
        arr1.push(arr4[k]);
      }
    }
  }
  return arr1;
}

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

不要吐槽我。。。

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

推荐阅读更多精彩内容