数据结构与算法之 leetcode 字符串题 回文串 / 最长公共子串 技巧

数据结构与算法阿木 发布于 8 天前 2 次阅读


数据结构与算法之 LeetCode 字符串题:回文串与最长公共子串技巧解析

在 LeetCode 上,字符串题目是算法挑战中的一大类,其中回文串和最长公共子串是两个非常经典的题目。这两个问题不仅考察了我们对字符串操作的理解,还涉及了动态规划、双指针等算法技巧。本文将围绕这两个主题,深入探讨其解题思路和代码实现。

一、回文串

回文串是指正读和反读都相同的字符串。例如,“abba”和“racecar”都是回文串。

1.1 解题思路

判断一个字符串是否为回文串,最直观的方法是将字符串反转,然后比较反转后的字符串与原字符串是否相同。这种方法的时间复杂度为 O(n^2),其中 n 是字符串的长度。

更高效的方法是使用双指针技术。我们定义两个指针,一个指向字符串的开头,另一个指向字符串的结尾。然后,我们逐个比较这两个指针所指向的字符,如果它们相同,则将两个指针都向中间移动一位,继续比较。如果遇到不相同的字符,则说明该字符串不是回文串。

1.2 代码实现

python

def is_palindrome(s: str) -> bool:


left, right = 0, len(s) - 1


while left < right:


if s[left] != s[right]:


return False


left += 1


right -= 1


return True


1.3 优化

对于空字符串和只包含一个字符的字符串,它们都是回文串。我们可以对上述代码进行优化,减少不必要的比较。

python

def is_palindrome(s: str) -> bool:


if len(s) < 2:


return True


left, right = 0, len(s) - 1


while left < right:


if s[left] != s[right]:


return False


left += 1


right -= 1


return True


二、最长公共子串

最长公共子串是指两个字符串中都存在的最长连续子串。例如,字符串“ABABC”和“BABCAC”的最长公共子串是“BABC”。

2.1 解题思路

解决最长公共子串问题,我们可以使用动态规划。定义一个二维数组 dp,其中 dp[i][j] 表示以 s1[i-1] 和 s2[j-1] 结尾的最长公共子串的长度。

状态转移方程为:如果 s1[i-1] == s2[j-1],则 dp[i][j] = dp[i-1][j-1] + 1;否则,dp[i][j] = 0。

2.2 代码实现

python

def longest_common_substring(s1: str, s2: str) -> str:


m, n = len(s1), len(s2)


dp = [[0] (n + 1) for _ in range(m + 1)]


max_len = 0


end_pos = 0


for i in range(1, m + 1):


for j in range(1, n + 1):


if s1[i - 1] == s2[j - 1]:


dp[i][j] = dp[i - 1][j - 1] + 1


if dp[i][j] > max_len:


max_len = dp[i][j]


end_pos = i


else:


dp[i][j] = 0


return s1[end_pos - max_len:end_pos]


2.3 优化

上述代码的时间复杂度为 O(mn),其中 m 和 n 分别是两个字符串的长度。我们可以通过空间优化来降低空间复杂度。

python

def longest_common_substring(s1: str, s2: str) -> str:


m, n = len(s1), len(s2)


dp = [0] (n + 1)


max_len = 0


end_pos = 0


for i in range(1, m + 1):


prev = 0


for j in range(1, n + 1):


temp = dp[j]


if s1[i - 1] == s2[j - 1]:


dp[j] = prev + 1


if dp[j] > max_len:


max_len = dp[j]


end_pos = i


else:


dp[j] = 0


prev = temp


return s1[end_pos - max_len:end_pos]


三、总结

本文介绍了 LeetCode 上两个经典的字符串题目:回文串和最长公共子串。通过分析解题思路和代码实现,我们了解了双指针技术和动态规划在解决字符串问题中的应用。在实际编程中,熟练掌握这些技巧将有助于我们解决更多类似的算法问题。