(一)FCC算法题Check for Palindromes Complete

纸上得来终觉浅,绝知此事要躬行。虽然通过《高程》学习了数组,字符串,正则表达式,但感觉还是流于表面,通过FCC的算法题可以很好地消化巩固这些知识。这里的答案首先是经过自己思考的,部分参考于stackover flow以及其他一些论坛,希望能为后来人留下一些指引。

题目链接:Check for Palindromes Complete

要求:检测字符是否是回文(指顺读和倒读都一样的词或短语,如refer),忽略大小写,空格,标点符号。

正则表达式这么写:/[^A-Za-z0–9]/g  或者 /[\W_]/g(正则表达式参考:《高程》、慕课网、regexper工具)

第一次写的时候直接用数组进行比较,发现虽然两个数组的内容是一样的,但是却不相等。

var reg = /[^a-zA-Z0-9]/g;

str.replace(reg,'').toLowerCase().split('')

//["m", "y", "a", "g", "e", "i", "s", "0", "0", "s", "i", "e", "g", "a", "y", "m"]

str.replace(reg,'').toLowerCase().split('').reverse()

//["m", "y", "a", "g", "e", "i", "s", "0", "0", "s", "i", "e", "g", "a", "y", "m"]

str.replace(reg,'').toLowerCase().split('') === str.replace(reg,'').toLowerCase().split('').reverse()

//false

这样的比较在对象上也行不通

var a = {name: "allen"}

//undefined

var b = {name: "allen"}

//undefined

a === b

//false

 

但在字符串上,这是行得通的

 

var s1='a'//undefined

var s2 = 'a'//undefined

s1 === s2//true

然后MDN看了Comparison operators:

比较操作符会为两个不同类型的操作数转换类型,然后进行严格比较。当两个操作数都是对象时,JavaScript会比较其内部引用,当且仅当他们的引用指向内存中的相同对象(区域)时才相等,即他们在栈内存中的引用地址相同。

两个数组显然在栈中的引用是不一样的,比较的时候自然会返回false。和字符串基础类型不一样的是,如果使用的是构造函数构建字符串,哪怕内容相同两者也返回false。

var a = new String('foo');

var b = new String('foo');

a===b //false;

a == b //false;

于是去了stackoverflow看了下数组的比较,一种比较巧妙的是使用JSON.stringify()方法将数组化为JSON格式。

var a1 = [1,2,3];

var a2 = [1,2,3];

console.log(a1==a2);    // Returns false

console.log(JSON.stringify(a1)==JSON.stringify(a2));    // Returns true

所以答案出来了:

function palindrome(str) {

    var reg = /[^a-zA-Z0-9]/g;

    var origin =  str.replace(reg,'').toLowerCase().split('');

   var reverse = origin.reverse();

    return JSON.stringify(origin) == JSON.stringify(reverse);

}

palindrome("eye");

palindrome("almostomla");

 

验证不通过。原因是sort()和reverse()两个方法都会改变原数组。修改的办法是先用slice(0)拷贝一个副本,这样就不会改变原来的数组了。

 

function palindrome(str) {

    var reg = /[^a-zA-Z0-9]/g;

    var origin =  str.replace(reg,'').toLowerCase().split('');

    var reverse = origin.slice().reverse();

   return JSON.stringify(origin) == JSON.stringify(reverse);

}

palindrome("A man, a plan, a canal. Panama");

当然,上面的做法相对麻烦,适用于比较复杂的数组(比如元素是有许多属性的的对象),所以这里直接转化字符串比较很方便。

function palindrome(str) {

    var re = /[\W_]/g;

    var oldStr = str.toLowerCase().replace(re, '');

    var reverseStr = oldStr.split('').reverse().join('');

    return reverseStr === oldStr;

}

palindrome("A man, a plan, a canal. Panama");

这里的reverseStr还可以这样生成:

reverseStr = Array.prototype.map.call(oldStr, function(x) {

    return x;

}).reverse().join('');

还有比较粗暴的方法是使用循环:

function palindrome(str) {

var re = /[^A-Za-z0-9]/g;

str = str.toLowerCase().replace(re, '');

var len = str.length;

for (var i = 0; i < len/2; i++) {

        if (str[i] !== str[len - 1 - i]) {

            return false;//只要有一个对应的位置不等就返回false

        }

    }

    return true;//全部通过

}

palindrome("A man, a plan, a canal. Panama");

 

你可能感兴趣的:(FCC)