LeetCodeの最長の回文文字列(409)、最長の回文部分文字列(5)、回文部分文字列(647)、バイナリ部分文字列のカウント(696)

1.最長の回文ストリング(409)

タイトル説明:

【シンプル】

大文字と小文字の文字列が含まれている場合、構成によって見つかった文字は、最も長い回文シーケンスによって発生します。

構築プロセスでは、大文字と小文字の区別に注意してください。たとえば、「Aa」は回文文字列として使用できません。

注:
ストリングの長さは1010を超えない想定されています。

例1:

输入:
"abccccdd"

输出:
7

解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7

トピックリンク

思考分析

要件:文字列のすべての文字に基づいて最長の回文文字列を作成します。
回文文字列:正と逆の両方を読み取る文字列

\ quad \ quad 回文では、最大で1文字のみが奇数回出現し、残りの文字は偶数回出現します。上手。偶数回の文字の場合、このすべての文字が回文の一部を形成できます。奇数回の文字の場合、このすべての文字-1が回文の一部を形成できます。最後に、1つ追加します。任意に奇数の文字が最長の回文文字列を形成できます。したがって、アイデアは次のとおりです。

  • 文字を数え、偶数を直接追加し、奇数を追加-1
  • 最後に、キャラクターが奇数回出現する場合は、1(回文の真ん中にあるキャラクター)を追加します。
class Solution:
    def longestPalindrome(self, s: str) -> int:
        odd=0 #标记是否出现过奇数次数的字符,0记没有出现过
        res=0 
        counts={}#统计字符次数
        for i in s:
            counts[i]=counts.get(i,0)+1
        for key in counts.keys():
            if counts[key]%2==0:
                res+=counts[key]
            else:
                res+=counts[key]-1
                odd=max(odd,counts[key])
        return res if odd==0 else res+1
  • 時間計算量:O(N)O(N)O N
  • スペースの複雑さ:O(S)O(S)O S 。ここで、Sは文字セット内の異なる文字の数です。

2.最長の回文部分文字列(5)

タイトル説明:

[中]
文字列sを指定し、sで最長の回文部分文字列を見つけます。
例1:

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

トピックリンク

解決策1:暴力法

  • すべての部分文字列をリストし、それが回文であるかどうかを判別し、最長の回文を保存します。
class Solution:
    #判断字符串是否为回文字符串
    def validate_palindrome(self,s:str,left:int,right:int) -> bool:
        if len(s)<right and left<0:
            assert("s length must greater than right,left must greater than or equal to zero")
        while left < right:
            if s[left]!=s[right]:
                return False
            left+=1
            right-=1
        return True

    def longestPalindrome(self, s: str) -> str:
        n=len(s)
        if n<2:
            return s
        #用来记录回文字符串
        palindrome_s=s[0]
        #记录回文字符串长度
        max_len=1
        for i in range(n-1):
            for j in range(i+1,n):
                if j-i+1>max_len and self.validate_palindrome(s,i,j):
                    palindrome_s=s[i:j+1]
                    max_len=j-i+1
        return palindrome_s
  • 時間計算量:O(n³)O(n³)O N ³ ループのために時間複雑度はO(n³)であるので、それは、パリンドロームO(N)であるか否かが判断される内部ループO(n²)用の二層。

  • スペースの複雑さ:O(1)定数変数。

  • 合格できますが、制限時間を超えて破棄します

問題解決2:動的計画法

  • ステータス:
    dp [i] [j]は、部分文字列s [i…j]が回文部分文字列であるかどうかを示します。部分文字列s [i…j]は、左閉区間と右閉区間として定義されます。 s [i]およびs [j]として。

  • 状態遷移方程式:
    dp [i] [j] =(s [i] == s [j])およびdp [i + 1] [j-1]

  • 初期化:
    初期化する場合、1文字は回文文字列である必要がある
    ため、文字列の長さが2未満の場合、それは回文文字列である必要があり、対角線は最初にtrueに初期化されます。つまり、dp [i] [ i] = true。

  • 出力:
    dp [i] [j] = trueになったらすぐに、部分文字列の長さと開始位置を記録します。これを傍受する必要はありません。これは、文字列を傍受するとパフォーマンスも低下するためです。今回は「開始位置」と「回文長さ」。

注:常に最初に小さな部分文字列の回文判定を取得してから、大きな部分文字列が小さな部分文字列の判定結果を参照できるようにします。つまり、フォームへの入力順序が非常に重要です。

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n=len(s)
        #考虑特殊情况:如果字符串的长度为1就是回文字符串
        if n<2:
            return s
        #创建一个二维列表用来保存每个字符串是否为回文字符串
        is_p= [[False] * n for _ in range(n)]
        #对角线上都是回文字符串,因为都是单个字符
        for i in range(n):
            is_p[i][i]=True
        #用来记录回文字符串的起始位置
        s_index=0
        max_len=1
        #遍历表格,计算字符串是否为回文字符串
        for j in range(1,n):
            for i in range(0,j):
                if s[i]==s[j]:
                    if j-i<3:
                        is_p[i][j]=True
                    else:
                        is_p[i][j]=is_p[i+1][j-1]
                else:
                    is_p[i][j]=False
                #记录最长的回文字符串
                current_len=j-i+1
                if is_p[i][j] and current_len>max_len:
                    max_len=current_len
                    s_index=i
        return s[s_index:(s_index+max_len)]
  • 時間計算量:O(n 2)O(n ^ 2)O n2
  • スペースの複雑さ:O(n 2)O(n ^ 2)O n2

問題解決3:中心拡散アルゴリズム

  • 各インデックスをトラバースし、このインデックスを中心として、「パリンドロームストリング」の中心の対称性を使用して両側に広げ、どこまで広がるかを確認します。

  • 回文の長さが奇数と偶数の場合、「回文中心」の形が異なります。

    • 奇数の回文文字列の「中心」は特定の文字です。たとえば、次のようになります。回文文字列「aba」の中心は文字「b」です。
    • 偶数回文の「中心」は、中央の2つの文字間の「ギャップ」です。たとえば、回文文字列「abba」の中心は、2つの「b」間の「ギャップ」です。
class Solution:
    def center_spread(self,s,size,left,right):
        """中心扩散寻找回文字符串
        :param s: 字符串
        :param size: 字符串的长度
        :param left: 开始寻找左边的位置
        :param right: 开始寻找右边的位置
        :return: 回文字符串,回文字符串的长度
        """
        i=left
        j=right
        #保证在寻找的过程中不发生越界,而且左右两个字符要相等
        while i>=0 and j<size and s[i]==s[j]:
            i-=1
            j+=1
        return s[i+1:j],j-i+1
    def longestPalindrome(self, s: str) -> str:
        size=len(s)
        if size<2:
            return s
        s_palindrome=s[0]
        max_len=1
        for i in range(size):
            #当回文字符串数是奇数时
            odd_palindrome,odd_len=self.center_spread(s,size,i,i)
            #当回文字符串是偶数的时候
            even_palindrom,even_len = self.center_spread(s,size,i,i+1)
            #获取最长的回文字符串
            cur_palindrome = odd_palindrome if odd_len > even_len else even_palindrom
            #更新最长的回文字符串
            if len(cur_palindrome) > max_len:
                s_palindrome = cur_palindrome
                max_len = len(cur_palindrome)

        return s_palindrome

  • 時間計算量:O(n 2)O(n ^ 2)O n2
  • スペースの複雑さ:O(1)O(1)O 1

3、回文子串(647)

タイトル説明:

[中]
文字列が与えられた場合、あなたのタスクは、この文字列に含まれる回文部分文字列の数を数えることです。

開始位置または終了位置が異なる部分文字列は、同じ文字で構成されている場合でも、異なる部分文字列と見なされます。

例1:

输入:"abc"
输出:3
解释:三个回文子串: "a", "b", "c"

例2:

输入:"aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

トピックリンク

思考分析

4.バイナリ部分文字列のカウント(696)

タイトル説明:

[単純]
文字列sが与えられた場合、同じ数の0と1を持つ空でない(連続した)部分文字列の数を数え、これらの部分文字列のすべての0とすべての1を組み合わせます。

繰り返される部分文字列は、出現する回数だけカウントする必要があります。

例1:

输入: "00110011"
输出: 6
解释: 有6个子串具有相同数量的连续10:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。

请注意,一些重复出现的子串要计算它们出现的次数。

另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。

例2:

输入: "10101"
输出: 4
解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续10

注意:

  • s.lengthは1から50,000の間です。
  • sには、「0」または「1」の文字のみが含まれます。

トピックリンク

思考分析

おすすめ

転載: blog.csdn.net/weixin_45666566/article/details/112604535
おすすめ