<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 s 的最大長度為 1000。
範例 1:
輸入: "babad" 輸出: "bab" 注意: "aba" 也是一個有效答案。
範例 2:
輸入: "cbbd" 輸出: "bb"
迴文:指一個正讀和反讀都相同的字串,例如,“aba” 是迴文,而 “abc” 不是。
即通過雙重遍歷來獲取目標字串所有的子串,push 到一個陣列裡面,然後根據字串長度排序,從最長字串開始迴圈校驗,第一個為迴文的子串就是我們要的結果
複雜度分析
/** * @param {string} s * @return {string} */ var longestPalindrome = function(s) { let m = [] let res = '' for(let i=0; i<s.length; i++) { for(let j = i; j < s.length; j++) { m.push(s.slice(i, j+1)) } } m.sort(function(a,b){ return b.length - a.length }) for (let i of m) { if (i === i.split('').reverse().join('')) { res = i break; } } return res }
上面程式碼在目標字串長度過大的時候,會超出時間限制,遠遠超出O(n^2) 的理想時間複雜度,這是因為過多的for 迴圈,js 自帶函數使用過多造成的,優化一下
var longestPalindrome = function(s) { let m = [] let res = '' for(let i=0; i<s.length; i++) { for(let j = i; j < s.length; j++) { if (s[i] != s[j]) break let ele = s.slice(i, j+1) if (ele === ele.split('').reverse().join('') && ele.length > res.length) { res = ele } } } return res }
看起來好多了,但是依然通不過Leecode 的測試,我覺得必須要把 slice split reverse join 這些函數都幹掉才行,也可能 JS 語言效率確實慢一些
反轉 S,使之變成 S'。找到 S 和 S' 之間最長的公共子串,判斷是否是迴文
複雜度分析
/** * @param {string} s * @return {string} */ var longestPalindrome = function(s) { let rs = s.split('').reverse().join('') let size = s.length let len = 0 let end = 0 let a = new Array(size) for (let i = 0; i < size; i++) { a[i] = new Array() } for (let i = 0; i < size; i++) { for(let j = 0; j < size; j++) { if (s[i] === rs[j]) { if (i > 0 && j > 0) { a[i][j] = a[i-1][j-1] + 1 } else { a[i][j] = 1 } if(a[i][j] > len) { let beforeIndex = size - 1 - j if (beforeIndex + a[i][j] -1 == i) { len = a[i][j] end = i } } } else { a[i][j] = 0 } } } return s.slice(end-len+1, end+1) }
遍歷一遍字串,以每個字元為中心向兩邊判斷,是否為迴文字串
複雜度分析
/** * @param {string} s * @return {string} */ var longestPalindrome = function(s) { let size = s.length let start = 0 let len = 0 //字串長度 // 奇數長度的迴文字串 for (let i = 0; i < size; i++) { let left = i - 1 let right = i + 1 while (left >= 0 && right < size && s[left] == s[right]) { left -- right ++ } if (right - left - 1 > len) { start = left +1 len = right -left -1 } } // 偶數長度的迴文字串 for (let i = 0; i < size; i++) { let left = i let right = i + 1 while (left >= 0 && right < size && s[left] == s[right]) { left-- right++ } if (right -left -1 > len) { start = left + 1 len = right -left -1 } } return s.slice(start, start + len) }
manacher 演演算法涉及中心拓展法、動態規劃,是manacher 1975年發明出來用來解決最長迴文子串的線性演演算法
// 第一步 var longestPalindrome = function(s) { let size = s.length if (size < 2) { return s } let str = addBoundaries(s, '#') let formatSize = 2 * size +1 let maxSize = 1 let start = 0 for (let i=0; i<formatSize; i++) { let curSize = centerSpread(str, i) if (curSize > maxSize) { maxSize = curSize start = (i - maxSize)/2 } } return s.slice(start, start + maxSize) } // 處理原字串 var addBoundaries = function(s, divide) { let size = s.length if (size === 0) { return '' } if (s.indexOf(divide) != -1) { throw new Error('引數錯誤,您傳遞的分割字元,在輸入字串中存在!') } return divide + s.split('').join(divide) + divide } // 輔助陣列 var centerSpread = function(s, center) { // left = right 的時候,此時迴文中心是一個空隙,迴文串的長度是奇數 // right = left + 1 的時候,此時迴文中心是任意一個字元,迴文串的長度是偶數 let len = s.length let i = center - 1 let j = center + 1 let step = 0 while (i >= 0 && j < len && s.charAt(i) == s.charAt(j)) { i-- j++ step++ } return step } longestPalindrome('ababadfglldf;hk;lhk')
manacher 演演算法的工作,就是對上面程式碼中的輔助陣列 p 進行優化,使時間複雜度的降到O(n^2)
// 完整 var longestPalindrome = function(s) { let size = s.length if (size < 2) { return s } let str = addBoundaries(s, '#') let formatSize = 2 * size +1 let p = new Array(formatSize).fill(0) let maxRight = 0 let center = 0 let maxSize = 1 let start = 0 for (let i=0; i<formatSize; i++) { if (i < maxRight) { let mirror = 2 * center - i; // Manacher 演演算法的核心 p[i] = Math.min(maxRight - i, p[mirror]); } // 下一次嘗試擴散的左右起點,能擴散的步數直接加到 p[i] 中 let left = i - (1 + p[i]); let right = i + (1 + p[i]); // left >= 0 && right < formatSize 保證不越界 // str.charAt(left) == str.charAt(right) 表示可以擴散 1 次 while (left >= 0 && right < formatSize && str.charAt(left) == str.charAt(right)) { p[i]++; left--; right++; } // 根據 maxRight 的定義,它是遍歷過的 i 的 i + p[i] 的最大者 // 如果 maxRight 的值越大,進入上面 i < maxRight 的判斷的可能性就越大,這樣就可以重複利用之前判斷過的迴文資訊了 if (i + p[i] > maxRight) { // maxRight 和 center 需要同時更新 maxRight = i + p[i]; center = i; } if (p[i] > maxSize) { // 記錄最長迴文子串的長度和相應它在原始字串中的起點 maxSize = p[i]; start = (i - maxSize) / 2; } } return s.slice(start, start + maxSize) } var addBoundaries = function(s, divide) { let size = s.length if (size === 0) { return '' } if (s.indexOf(divide) != -1) { throw new Error('引數錯誤,您傳遞的分割字元,在輸入字串中存在!') } return divide + s.split('').join(divide) + divide } longestPalindrome('babb')
到此這篇關於JavaScript求解最長迴文子串的方法分享的文章就介紹到這了,更多相關JavaScript最長迴文子串內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45