-
Notifications
You must be signed in to change notification settings - Fork 1.4k
FCC中级算法题目小记
huluoyang edited this page Oct 13, 2016
·
2 revisions
本文首发于我的个人网站.欢迎围观!
大约2个月前,我在知乎上得知一个学习编程的网站 : FreeCodeCamp中文站,FreeCodeCamp英文站。该网站采用关卡式学习方式,免费教授全栈开技能。
- 下面是它的简单介绍:
- 下图为在此网站可获得的开发技能:
在FCC全套课程中,前端工程师技能中最难的当属 Javascript(简称JS)了。所谓算法编程 (Algorithm Scripting),就是设计JS函数(function)来解各种算法题。
下面是我刚完成的中级算法编程 (Intermediate Algorithm Scripting) 练习题:
这些题目我做过两遍,做第一遍时,笔者对JS各种数据类型的方法或属性不甚了解,常常苦思冥想不得解,最后虽然题目都做完了,但是代码冗长且混乱,滥用循环语句。
做第二遍的时候,我开始思考这些题目的更优的解法,反复琢磨Array,String,Object等数据类型的常用方法和属性,添加必要的注释,最后完成了第二遍练习,同时将前后两次的代码整理到了印象笔记中。
下面贴出几道我认为比较有意思的算法题。code1表示第一次给出的答案,code2表示第二次的答案。两个答案都能解决题目问题,但第二次的代码明显优于第一次。
一开始看到题目,我以为是FCC中文站翻译出错,应该是where are you,后来查了一下thou的意思,居然有你的意思。
题目:
code1:
function where(collection, source) {
var arr = [];
// What's in a name?
var sourArr = Object.keys(source);
for(var i =0, len1 = collection.length; i < len1; i++) {
var num = 0;
for(var j = 0,len2 = sourArr.length; j < len2; j++) {
if(!collection[i].hasOwnProperty(sourArr[j])){
break;
} else {
if(collection[i][sourArr[j]] === source[sourArr[j]]) {
num += 1;
}
}
}
if( num ===len2 ) {
arr.push(collection[i]);
}
}
return arr;
}
//test
where([{ "a": 1, "b": 2 }, { "a": 1 }, { "a": 1, "b": 2, "c": 2 }], { "a": 1, "b": 2 });
- 可以看到上述代码用了“无数”个for循环和if-else判断,缺少注释,难以一目了然。
code2:
function where(collection, source) {
var keys = Object.keys(source); //获得source的key数组
return collection.filter(function(obj){ //筛选出使keys满足断言函数的对象元素
return keys.every(function(e){ //断言函数判断obj是否包含所有source的键值对
return obj.hasOwnProperty(e) && obj[e] === source[e];
});
});
}
//test
where([{ "a": 1, "b": 2 }, { "a": 1 }, { "a": 1, "b": 2, "c": 2 }], { "a": 1, "b": 2 });
- code2 明显精简了许多,增加了必要的注释。去掉了if和for语句。采用Object.key()和Array的filter(),every() 加合适的逻辑表达式则可解决此题。
- 采用逆向思维解此题,最后一步是从collection数组中筛选符合一定条件的对象元素返回,倒数第二步是设计合适的断言函数,只有包含source中每组键值对的对象元素才满足条件,为此应该采用逻辑与表达式来对每个键值对进行判断。
- 值得一提的是,本题中用到了闭包。
题目:
code1:
function translate(str) {
var letters = str.split("");
var newStr = "";
for(var i = 0, len = letters.length; i < len; i++) {
if("aeiou".indexOf(letters[i]) !== -1) {
var index = i;
if (index === 0) {
letters.push("way");
newStr = letters.join("");
} else {
var change = str.substr(0,index);
newStr = str.substr(index) + change + "ay";
}
break;
}
}
return newStr;
}
//test
translate("glove");
code2:
function translate(str) {
var newStr = "";
var index = str.search(/[aoeiu]/); //获得第一个元音字母的索引值,并根据索引值是否为0来判断返回什么样的值:
return index === 0 ? str + "way" : str.substr(index) + str.substr(0,index) +"ay";
}
//test
translate("paragraphs");
- 此题不多说,code2 完爆 code1 !
本文篇幅有限,其它题目不再介绍。
通过完成FCC算法编程题,对之前在犀牛书中看到但是忽视或者忘记的细节进行了回忆与巩固,同时锻炼了逻辑思考能力,收获颇多!
以上。 2016.10.12
非常欢迎来这里写自己的学习心得。 code1 与 code2 的比较很有意思,这个循序渐进的代码精进过程很值得学习。