Advertisement

LeetCode 5. 最长回文子串(双指针与中心扩展法)

  •  5星
  •     浏览量: 0
  •     大小:None
  •      文件类型:PDF


简介:
本题讲解如何使用双指针及中心扩展法寻找字符串中最长的回文子串,适合对算法和数据结构感兴趣的读者。 在LeetCode的第5题《最长回文子串》中,目标是找到给定字符串` s `中的最长回文子串。回文串是指正读反读都能读通的字符串,例如 aba 和 abba 都是回文串。本题要求的解决方案需在字符串长度不超过1000的情况下进行。 解决问题的关键在于运用双指针和中心扩展算法。这里有两个主要的方法:**法一** 通过两个指针` l `和` r `从中间向外扩展,首先考虑奇数长度的情况(即以一个字符为中心),然后是偶数长度的情况(即以相邻的两个字符为起点)。这两种情况可以通过调用辅助函数` helper `来处理。在该辅助函数中使用一个循环不断检查当前指针所指向的字符是否相等,并根据结果调整指针位置,直到找到最长回文子串或遇到不匹配为止。 **法二** 则是将上述两种情况进行合并,在每个可能的位置同时调用` helper `处理单个字符和相邻两个字符的情况。通过比较这两种情况下的回文长度来选择最优解,使得代码更为简洁高效。 在实现时定义一个类` Solution `,其中包含主方法` longestPalindrome `以及辅助函数` helper `。主方法遍历字符串中的每个位置,并尝试以此为中心进行扩展搜索以找到可能的最长回文子串;最后返回整个过程中发现的最大长度的回文子串。 以下是一个具体的实现: ```python class Solution: def longestPalindrome(self, s): res = for i in range(len(s)): # 奇数情况和偶数情况分别调用helper函数,并通过max选择最长的结果。 res = max(self.helper(s, i, i), self.helper(s, i, i + 1), res, key=len) return res def helper(self, s, l, r): # 在边界条件内,向两边扩展寻找回文子串 while l >= 0 and r < len(s) and s[l] == s[r]: l -= 1 r += 1 # 返回以l和r为中心的最长回文字符串(注意循环结束时已经超出边界) return s[l + 1:r] ``` 对于输入` s = babad `,该代码会输出结果为` bab `,这是给定字符串中的一个最长回文子串。 这种双指针中心扩展算法的时间复杂度为O(n^2),空间复杂度为O(1)。尽管存在更高效的动态规划解决方案,但对于本题的规模来说这种方法已经足够高效。

全部评论 (0)

还没有任何评论哟~
客服
客服
  • LeetCode 5.
    优质
    本题讲解如何使用双指针及中心扩展法寻找字符串中最长的回文子串,适合对算法和数据结构感兴趣的读者。 在LeetCode的第5题《最长回文子串》中,目标是找到给定字符串` s `中的最长回文子串。回文串是指正读反读都能读通的字符串,例如 aba 和 abba 都是回文串。本题要求的解决方案需在字符串长度不超过1000的情况下进行。 解决问题的关键在于运用双指针和中心扩展算法。这里有两个主要的方法:**法一** 通过两个指针` l `和` r `从中间向外扩展,首先考虑奇数长度的情况(即以一个字符为中心),然后是偶数长度的情况(即以相邻的两个字符为起点)。这两种情况可以通过调用辅助函数` helper `来处理。在该辅助函数中使用一个循环不断检查当前指针所指向的字符是否相等,并根据结果调整指针位置,直到找到最长回文子串或遇到不匹配为止。 **法二** 则是将上述两种情况进行合并,在每个可能的位置同时调用` helper `处理单个字符和相邻两个字符的情况。通过比较这两种情况下的回文长度来选择最优解,使得代码更为简洁高效。 在实现时定义一个类` Solution `,其中包含主方法` longestPalindrome `以及辅助函数` helper `。主方法遍历字符串中的每个位置,并尝试以此为中心进行扩展搜索以找到可能的最长回文子串;最后返回整个过程中发现的最大长度的回文子串。 以下是一个具体的实现: ```python class Solution: def longestPalindrome(self, s): res = for i in range(len(s)): # 奇数情况和偶数情况分别调用helper函数,并通过max选择最长的结果。 res = max(self.helper(s, i, i), self.helper(s, i, i + 1), res, key=len) return res def helper(self, s, l, r): # 在边界条件内,向两边扩展寻找回文子串 while l >= 0 and r < len(s) and s[l] == s[r]: l -= 1 r += 1 # 返回以l和r为中心的最长回文字符串(注意循环结束时已经超出边界) return s[l + 1:r] ``` 对于输入` s = babad `,该代码会输出结果为` bab `,这是给定字符串中的一个最长回文子串。 这种双指针中心扩展算法的时间复杂度为O(n^2),空间复杂度为O(1)。尽管存在更高效的动态规划解决方案,但对于本题的规模来说这种方法已经足够高效。
  • LeetCode 409:(详解版)
    优质
    本文章详细解析了LeetCode第409题“最长回文串”,提供了多种解法及其Python代码实现,并深入探讨了解题思路和算法优化。 给定一个包含大写字母和小写字母的字符串,我们要找到通过这些字母构造成的最长回文串,并且注意区分大小写。 解题思路如下:由于回文串是对称的,我们可以通过统计每个字符出现次数来解决这个问题。具体来说: 1. 统计每个字符在给定字符串中的出现次数。 2. 对于每一对相同的字符(即偶数次),我们可以直接将这对字符加入到可能构成最长回文的部分中去。 3. 如果某个字符出现了奇数次,我们只能使用该字符的最接近的最大偶数值部分来构建回文串。此外,在最终结果中可以考虑加上一个出现次数为1的字符作为中心。 最后,我们需要判断是否能构造出长度为奇数的最长回文串;如果消除掉所有成对出现的字符后剩余字符串不为空,则说明存在这样的可能性(即总消去的数量小于原始字符串长度)。 以下是实现该思路的具体代码: ```python from collections import Counter class Solution: def longestPalindrome(self, s: str) -> int: cnt = Counter(s) res = sum(i // 2 * 2 for i in cnt.values()) return res + 1 if res < len(s) else res ``` 这段代码首先通过`Counter`类统计每个字符出现的次数,然后计算所有成对出现的字符数,并最终判断是否可以构建一个以某个奇数次出现的单个字符为中心的最大回文串。 这种方法简洁高效,在处理长度不超过10^10字符串时非常适用。当然还有其他方法如动态规划或Manachers Algorithm等可用于解决该问题,但本题中上述计数法已经足够有效了。
  • 优质
    《最长的回文子串》是一道经典的计算机算法题目,要求在给定字符串中找到长度最长且正反读相同的子串,挑战编程者优化算法以高效解决问题。 最长回文子串 给定一个字符串str,返回str中最长回文子串的长度。 举例: - str=123,其中的最长回文子串为”1″、“2″或者”3”,所以返回1。 - str=abc1234321ab,其中的最长回文子串为”1234321″,所以返回7。 暴力遍历法 以每个字符为中心向外扩展检查其左右两边是否相同。最坏情况下每次扩至字符串两端,因此时间复杂度为O(N²),N是字符串长度。 注意: - 回文串是指正读反读都能保持相同的字符串,如“madam”或“121”。 最长回文子串问题可以通过多种算法解决,其中暴力遍历法是最简单但效率较低的方法。该方法以每个字符为中心向外扩展检查其左右两边的字符是否相等,从而判断这个字符是否属于一个回文子串。对于每个字符都需要进行两次遍历来找到可能的最长回文子串,因此时间复杂度为O(N²)。 为了提高效率可以采用Manacher算法(也称为马拉车算法)。该算法利用了回文串的对称性来减少重复计算。首先构建一个辅助字符串,在原字符串中的每个字符间插入特殊字符(例如#),这样可以让每个回文子串的中心在辅助字符串中显式存在。然后,维护一个回文半径的最大值p_r和对应的中心索引index,遍历过程中如果当前位置i不在当前回文子串的对称范围内就尝试向两边扩展;若在范围之内就可以利用对称性快速更新回文半径。这样Manacher算法的时间复杂度降低到O(N),大大提高了效率。 以下是暴力遍历和Manacher算法的Python代码实现: ```python # 暴力遍历最长回文子串 def solution(s): max_len = 0 for i in range(len(s)): count = 1 j = 1 while i - j >= 0 and i + j < len(s): if s[i - j] != s[i + j]: break count += 2 j += 1 max_len = max(max_len, count) return max_len # Manacher算法 def get_manacher_str(s): char_arr = [# + c for c in s + # + .join(list(reversed(s)))] return .join(char_arr) def get_long_pal_sub_str_len(s): manacher_str = get_manacher_str(s) pal_arr = [0] * len(manacher_str) index = -1 p_r = -1 max_len = 0 for i in range(len(manacher_str)): if i < p_r: pal_arr[i] = min(pal_arr[2 * index - i], p_r - i) else: pal_arr[i] = 1 while i - pal_arr[i] >= 0 and i + pal_arr[i] < len(manacher_str) and manacher_str[i - pal_arr[i]] == manacher_str[i + pal_arr[i]]: pal_arr[i] += 1 if i + pal_arr[i] > p_r: index = i p_r = i + pal_arr[i] if max_len < pal_arr[i]: max_len = pal_arr[i] return max_len - 1 # 测试 s1 = 123 s2 = abc1234321ab print(solution(s1)) # 输出: 1 print(solution(s2)) # 输出: 7 print(get_long_pal_sub_str_len(s1)) # 输出: 0 (因特殊字符,长度减一) print(get_long_pal_sub_str_len(s2)) # 输出: 7 ``` 在实际应用中Manacher算法因其高效的性能被广泛使用。通过理解和掌握这种算法可以更好地解决与回文串相关的复杂问题,并提高程序的运行效率。
  • Python寻找的算
    优质
    本篇技术文章探讨了如何在Python编程语言中实现寻找字符串中最长回文子串的有效算法。通过分析不同方法的效率和复杂度,本文提供了简洁而高效的代码示例。 给定一个字符串,任务是在这个字符串中找到符合回文性质的最长子串。所谓回文性是指类似“aba”、“ababa”、“abba”的字符串形式,当然单个字符以及两个相邻相同的字符也满足这种性质。 面对这个问题时,最初的想法是通过暴力枚举来解决:从所有可能的字串起点开始逐一判断是否符合回文条件,并记录最长长度。然而这种方法的时间复杂度较高,在最坏的情况下可以达到O(N*N)。因此,这里提出一种优化方案——不是以子串的起始点为基准进行遍历,而是选择字符串中每个位置作为中心(包括字符间的间隙),然后向两边扩散来判断回文性质。这种改进后的算法在处理只包含单一字符的情况时效率会有显著提升。 根据上述优化思路,我重新组织了这段描述以提高清晰度和简洁性。
  • 怎样找出字符
    优质
    本篇教程将详细介绍如何识别和提取给定文本中出现的最长回文序列。通过具体算法解析与实例演示相结合的方式,帮助读者掌握解决此类问题的方法技巧。 问题描述: 给定一个字符串,求出它的一个最长的回文子串。所谓回文子串指的是一个字符串从左到右和从右到左遍历得到的序列是相同的。例如“abcba”是一个回文子串,而“abcab”就不是。 思考 如何确定一个字符串是否为回文串?这是一个关键的问题。根据它的定义,它从左往右和从右往左读取的结果是一样的,因此可以想到使用两个指针来解决这个问题:一个在头端,另一个在尾端。每次移动一个位置,并比较这两个指针所指向的字符是否相等。如果直到两个指针相遇或相邻时都没有出现不匹配的情况,则说明这个字符串是回文串;否则就不是。 由于字符串索引本身就是天然的指针,因此不需要特别设计额外的指针来完成这一任务。判断一个字符串是否为回文串的时间复杂度可以达到O(n),其中n代表该字符串长度。
  • C语言问题
    优质
    本篇内容探讨了如何在C语言中解决寻找字符串中最长回文子串的问题,包括算法原理与实现方法。 自己编的,希望大家指点!这是西工大期末考试的一道题目,我花费了很长时间才完成。
  • Python编程求
    优质
    本篇文章探讨了如何使用Python编写程序来寻找字符串中最长的回文子串,并计算其长度。通过算法优化,提高代码效率和执行速度。 给定一个字符串,要求出它最长的回文子串长度。例如输入字符串35534321,它的最长回文子串是3553,所以返回值为4。 最容易想到的方法是枚举所有的子串,并逐一判断是否为回文串,最后返回最长的那个。然而这种方法耗时较长,难以接受。 那么有没有更高效的方法来查找回文子串呢?答案当然是肯定的——中心扩展法。选择一个元素作为中心点,然后向外扩散寻找以该元素为中心的最大回文子串。 但是又出现了新的问题:回文子串长度可能是基数(奇数)也可能是偶数,在长度为偶数的情况下,并不存在明确的中心元素。那么是否有一种方法可以将奇偶长度的子串统一处理呢?答案是肯定的,这就是Manacher算法。
  • Python编程求
    优质
    本文章介绍了一种使用Python语言实现寻找字符串中最长回文子串长度的方法,通过算法优化来提高效率。 最长回文子串问题是指给定一个字符串后求其最长的回文子串长度。如果一个字符串正着读和反着读是一样的,则称它为回文串。接下来我们探讨这个问题。
  • LeetCode练习得——#3. 不含重复字符的字符
    优质
    本篇文章记录了我在LeetCode上解决“最长不含重复字符的子字符串”问题的心得体会,分享了解题思路和优化过程。 难度:中等 题目描述: LeetCode中的第3题是一个经典的字符串处理问题,名为“无重复字符的最长子串”。该问题要求找到给定字符串中最长的一个不含任何重复字符的子串。例如,对于输入字符串 pwwkew ,最大的不包含重复字符的子串是 wke, 长度为 3。 解题分析: 解决这个问题的有效方法之一就是使用滑动窗口策略和哈希表来追踪每个字符及其在该字符串中的最新位置。具体步骤如下: 1. 初始化一个空字典 `d` 来存储字符以及它们的索引。 2. 定义两个变量:`start` 用于记录当前子串的起始位置,初始值设为 -1;而 `max_len` 则用来跟踪最长无重复字符子串的长度,初始化为0。 3. 遍历输入字符串中的每个字符,使用索引 `i` 表示当前迭代的位置。 4. 对于每一个字符,检查它是否已经存在于字典中。如果存在且其对应的值大于 `start` ,这表明该字符是重复出现的,并需要更新 `start` 为这个重复字符上一次出现时的索引位置。 5. 如果当前处理到的字符不在字典里或者它的上次出现的位置小于等于 `start`, 则将该字符及其当前位置添加进字典中,以记录它最新的位置信息。 6. 在每次迭代结束的时候,计算从 `i - start` 得出当前子串长度,并与之前的最大值进行比较。如果当前子串更长,则更新最大值为新的长度。 7. 完成遍历后,返回 `max_len` 作为最长无重复字符子串的长度。 代码实现: ```python class Solution: def lengthOfLongestSubstring(self, s: str) -> int: start = -1 max_len = 0 d = {} for i in range(len(s)): if s[i] in d and d[s[i]] > start: start = d[s[i]] d[s[i]] = i if i - start > max_len: max_len = i - start return max_len ``` 模拟笔试: 在实际的编程面试或笔试中,你可能需要提供完整的代码实现,包括输入输出部分。以下是一个示例: ```python def main(): s = input() # 用户输入字符串,例如 pwwkew solution = Solution() output = solution.lengthOfLongestSubstring(s) print(output) # 输出最长无重复字符子串的长度 if __name__ == __main__: main() ``` 此模拟笔试代码中,我们首先接收用户提供的输入字符串 `s` ,然后调用类 `Solution` 的方法计算最长不含重复字符子串的长度,并将该结果输出。 这道题目考察了对字符串处理、滑动窗口技术和哈希表应用的理解。通过使用字典来存储每个字符的位置信息,我们能够在 O(n) 时间复杂度内解决这个问题,其中 n 是输入字符串的长度。此外,这也锻炼了解决问题时的设计和优化能力。
  • 解析Python公共公共序列的实现方
    优质
    本文深入探讨了在Python中实现最长公共子串和最长公共子序列的方法,通过详细的代码示例帮助读者理解两者之间的区别及应用场景。 本段落详细介绍了Python中实现最长公共子串和最长公共子序列的方法,并分享给读者参考。希望能帮助大家更好地理解这些概念和技术。