leetcode-5-最長の回文サブストリング

創造を続け、成長を加速させましょう!「ナゲッツデイリーニュープラン・6月アップデートチャレンジ」に参加した初日です。クリックしてイベントの詳細をご覧ください。

トピックアドレス

文字列が与えられた場合、  で最長の回文部分文字列sを見つけます 。s

例1:

输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。
复制代码

例2:

输入: s = "cbbd"
输出: "bb"
复制代码

 

ヒント:

  • 1 <= s.length <= 1000
  • s 数字と英字のみで構成されます

この記事の問題の意味は非常に単純で、解決するのは難しくありません。考えられるすべてのサブストリングをトラバースして、それが回文であるかどうかを判断するだけで十分です。ただし、このアルゴリズムの時間計算量はO(n´³)、時間計算量です。が高すぎると、制限時間が超過します。時間計算量のある2つのアルゴリズムO(n²)を。

問題解決のアイデア-動的計画法

いわゆる回文文字列は、両端から中央、または中央から両端にあり、各文字が等しいiことjから、下付き文字から下付き文字までの部分文字列が回文であることがわかります。そしてs[i-1]===s[j+1]、下付きi-1j+1文字も回文です。上記の導出から、移動と戻りの状態定義と遷移方程式を定義できます。
状態の定義:下付き文字dp[i][j]から下付き文字iへの部分文字列が回文遷移方程式jであるかどうかを示します単一の文字が回文であるため、この条件に基づいてすべてを初期化し、派生するま​​で部分文字列の長さを拡張し続けることができますすべての部分文字列の結果を取得します。
dp[i][j] = dp[i+1][j-1] && s[i]===s[j]
dp[i][i] = true

コード

var longestPalindrome = function(s) {
    const len = s.length

    if(len===1){
        return s
    }

    const dp = Array(len)

    for(let i = 0;i<len;i++){
        dp[i] = []
        dp[i][i] = true
    }

    let maxLen = 1
    let beginIndex = 0

    for(let L = 2;L<=len;L++){
        for(let i = 0;i<=len-L;i++){
            const j = i+L-1

            if(s[i]!==s[j]){
                dp[i][j] = false
            }else{
                if(i===j-1){
                    dp[i][j] = true
                }else{
                    dp[i][j] = dp[i+1][j-1]
                }
            }

            if(dp[i][j] && j-i+1>maxLen){
                maxLen = j-i+1
                beginIndex = i
            }
        }
    }

    return s.substring(beginIndex,beginIndex+maxLen)
}
复制代码

問題解決のアイデア-センターの拡張

問題に移動して戻るという考えの説明により、下付き文字から下付き文字への部分文字列が回文である場合、下付き文字から下付き文字へも回文でiあることがわかります。このことから、考えられるすべての回文中心を列挙することができ、両側に拡張することによってすべての回文部分文字列を見つけることができ、それによって最長の回文部分文字列が得られることが想像できます。js[i-1]===s[j+1]i-1j+1

コード

function getMaxBackTextString(s,len,l,r){
    if(s[l]!==s[r]){
        return 0
    }
    let res = r-l+1
    while(l>0 && r<len-1){
        l--
        r++
        if(s[l]===s[r]){
            res+=2
        }else{
            break
        }
    }

    return res
}
var longestPalindrome = function(s) {
    const len = s.length
    if(len===1){
        return s
    }

    let maxLen = 1
    let beginIndex = 0

    for(let i = 0;i<len;i++){
        const len1 = getMaxBackTextString(s,len,i,i)
        const len2 = getMaxBackTextString(s,len,i,i+1)

        if(len1>maxLen){
            maxLen = len1
            beginIndex = i-(len1-1)/2
        }
        if(len2>maxLen){
            maxLen = len2
            beginIndex = i-(len2-2)/2
        }
    }

    return s.substring(beginIndex,beginIndex+maxLen)
}
复制代码

どちらも時間計算量は同じですが、動的計画法の初期化プロセスが完了し、その導出プロセスが完了しているO(n²)ため、中心拡張は動的計画法よりも効率的であることに注意してください。O(n)中央の拡張方法は、拡張できない場合に停止し、各拡張は2文字の長さです。
その理由の一部は、動的計画法の空間の複雑さもO(n²)であるのに対し、中央拡張の空間の複雑さはわずかであるということO(1)です。

これまで のところ、 leetcode-5-最長の回文サブストリングを完了しました

ご質問やご提案がございましたら、メッセージを残してご相談ください。

おすすめ

転載: juejin.im/post/7101700819656900615