回文在維基百科中的定義:回文,亦稱回環(huán),是正讀反讀都能讀通的句子,亦有將文字排列稱圓圈者,是一種修辭方式和文字游戲。
從定義我們可以知道一個字符串是不是回文,可以判斷該字符串是否等于該字符的倒順序,下面我們用JavaScript實現(xiàn)一個判斷是否為回文的函數(shù)isPalindrome:
function isPalindrome(str) {
return str.split('').reverse().join('') === str;
}
isPalindrome('cabac');
// => true
isPalindrome('abc');
// => false
以上這個isPalindrome函數(shù)從功能的角度上看是實現(xiàn)了,代碼就一行,看起來也簡潔。但是從性能的角度看很糟糕。要先把字符轉成數(shù)組,然后使用數(shù)組的reverse()取反數(shù)組,最后再把數(shù)組轉成字符進行比較,這是過程看起來就低效的樣子。那我們優(yōu)化一下:
function isPalindrome_1(str) {
let reverseStr = '';
let len = str.length;
while(len !== 0) {
len -= 1;
reverseStr += str[len];
}
return reverseStr === str;
}
isPalindrome_1去掉了數(shù)組轉換的過程,直接使用while循環(huán)拼一個str的倒序字符串和原str進行比較,判斷是否為回文。這應該為比isPalindrome的實現(xiàn)在性能上會快很多(具體數(shù)值測試放后面)。
我們再看看cabac這個回文,我們發(fā)現(xiàn)以b為中心,左邊的第一個位置的字符和右邊的第一個位置的字符相同,第二個位置的字符也是相同。有了這個規(guī)律我們又可以進行優(yōu)化,我們看一下實現(xiàn)代碼:
function isPalindrome_2(str) {
let index;
let len = str.length;
var testEndingIndex = len / 2;
for (index = 0; index < testEndingIndex; index++) {
if (str[index] !== str[len - 1 - index]) {
return false;
}
}
return true;
}
isPalindrome_2對字符串循環(huán)的減少來一半,具體性能上提升多少呢?我們放后面測試。我們再看isPalindrome_2是否還有優(yōu)化的看空間?
不難發(fā)現(xiàn)在for循環(huán)里面每次都去進行len - 1的運算,這完全沒有必要。可以把len-1放for外進行優(yōu)化。
function isPalindrome_3(str) {
let index;
let len = str.length - 1;
var testEndingIndex = len / 2;
for (index = 0; index < testEndingIndex; index++) {
if (str[index] !== str[len - index]) {
return false;
}
}
return true;
}
現(xiàn)在對isPalindrome進行了三次的優(yōu)化,下面我們測試一下這四個函數(shù)在性能上的區(qū)別:
const count = 1000000;
const str = 'cabac';
function test(fn, count) {
const start = Date.now();
for (let i = 0; i < count; i++) {
fn();
}
console.log(Date.now() - start);
}
test(() => {
isPalindrome(str);
}, count);
test(() => {
isPalindrome_1(str);
}, count);
test(() => {
isPalindrome_2(str);
}, count);
test(() => {
isPalindrome_3(str);
}, count);
//isPalindrome => 346
//isPalindrome_1 => 53
//isPalindrome_2 => 26
//isPalindrome_3 => 19
從測試數(shù)據(jù)上,可以很明顯的看到四個函數(shù)之間的性能差異。
總結
在代碼編寫的過程中,減少沒有必要的運算過程,選擇最佳的算法實現(xiàn),可以在性能上有很大的提升。