在回文算法中講性能優(yōu)化

回文在維基百科中的定義:回文,亦稱回環(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-1for外進行優(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),可以在性能上有很大的提升。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,557評論 0 13
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,656評論 1 32
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結構(3).初始化時...
    歐辰_OSR閱讀 30,241評論 8 265
  • ??引用類型的值(對象)是引用類型的一個實例。 ??在 ECMAscript 中,引用類型是一種數(shù)據(jù)結構,用于將數(shù)...
    霜天曉閱讀 1,219評論 0 1
  • 經(jīng)過前一天的學習,一晚上腦子里排山倒海地思索,連做夢都在皺著眉頭劃重點……終于來到了第二天……醒來發(fā)現(xiàn)昨天的任務沒...
    蘑菇堯堯樂閱讀 329評論 0 0

友情鏈接更多精彩內(nèi)容