问题描述
解法一
将两个字符串先转化为数组,然后再进行数组的排序,最后再转化成字符串进行 === 的比较。
var isAnagram = function(s, t) {
if(s.length != t.length) return false
let sarr = Array.from(s);
let tarr = Array.from(t);
if(sarr.sort().toString() === tarr.sort().toString()){
return true;
}
return false;
};
//此种思路若 js API 用的溜,两行代码搞定
var isAnagram = function(s, t) {
if(s.length != t.length) return false;
return s.split('').sort().join('') == t.split('').sort().join('');
}
这种方法固然可以,但是该方法的时间复杂度是 js 数组内置排序算法的时间复杂度,最好的也是 o(nlogn),空间复杂度为:o(n)
解法二
该方法是在一次面试中,面试官提醒说时间复杂度为 o(n) 时提醒的一种思路。
就是,使用哈希的方式,从字符串映射成对象,对象的 key 是字符,对应的 value 是该字符出现的次数,然后再比较两个对象是否相等就可以了。
var isAnagram = function(s, t) {
if(s.length != t.length) return false
let sobj = {}, tobj = {};
for(let i = 0; i < s.length; i++){
if(sobj[s[i]] != undefined){
sobj[s[i]]++
}else{
sobj[s[i]] = 1
}
if(tobj[t[i]] != undefined){
tobj[t[i]]++
}else{
tobj[t[i]] = 1
}
}
for(let obj in sobj){
if(sobj[obj] != tobj[obj])
return false
}
return true
};
这种方式要比前一种好些,该方法的时间复杂度为 o(n),空间复杂度为 o(n)
解法三
这种方法是在 leetcode 上看到的大多数人的做法,就是将 26 个小写英文字符一一对应数组的 index,数组的值为当 s 中该字符出现时加1,当 t 中该字符出现时减1,最后判断数组中每一项结果是否为 0 即可。
var isAnagram = function(s, t) {
if(s.length != t.length) return false
let arr = Array(26).fill(0)
let baseIndex = 'a'.charCodeAt(0)
for(let i = 0; i < s.length; i++){
arr[s[i].charCodeAt(0) - baseIndex]++
arr[t[i].charCodeAt(0) - baseIndex]--
}
for(let i = 0; i < arr.length; i++){
if(arr[i] != 0)
return false
}
return true
};
但是这种方法有局限性,就像问题中进阶问题写的,当字符串中不只是有小写字母,而是有所有字符时,这种方式就不能通用了。
解法四
在解法二和解法三的基础上进行取其精华去其糟粕,得到另一种解题方法如下:
var isAnagram = function(s, t) {
if(s.length != t.length) return false
let obj = {}
for(let i = 0; i < s.length; i++){
if(obj[s[i]] === undefined){
obj[s[i]] = 1
}else{
obj[s[i]]++
}
if(obj[t[i]] === undefined){
obj[t[i]] = -1
}else{
obj[t[i]]--
}
}
for(let key in obj){
if(obj[key] != 0)
return false
}
return true
};
这种是结合了第三种解题方法的思路,用在了第二种解题方法中,和第二种效率差不多。