美文网首页freeCodeCamp
FreeCodeCamp中级算法(更新中)

FreeCodeCamp中级算法(更新中)

作者: 少年vv | 来源:发表于2016-11-14 22:21 被阅读263次

    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]);
    

    不要吐槽我。。。

    相关文章

      网友评论

      • whuisu:那个第八个是丢失的字母~不是丢失的信哈哈哈

      本文标题:FreeCodeCamp中级算法(更新中)

      本文链接:https://www.haomeiwen.com/subject/ixwyuttx.html