不知道为啥整了一些入门题目,本来以为是排序类的题目,但是做下来看着都是字符串相关的,倒是和排序没有一丁点关系。
题目有难有易,也涉及了哈希表、动态规划相关的知识,不过都比较简单,相对还算容易理解。
个人觉得没有必要单独拎出来叫入门题目,叫字符串类型题目倒是挺合适的。
废话不说了,开始一个一个题目来攻克,并写出来攻克时的心路历程。
627. 最长回文串
给出一个包含大小写字母的字符串。求出由这些字母构成的最长的回文串的长度是多少。
数据是大小写敏感的,也就是说,“Aa” 并不会被认为是一个回文串。
class Solution:
"""
@param s: a string which consists of lowercase or uppercase letters
@return: the length of the longest palindromes that can be built
"""
def longestPalindrome(self, s):
# write your code here
# 这个题目初看时没有理解,看了一会才明白不是要子串,类似于要子序列
# 那就找出不能配对的字符有多少个,最长回文串的长度是减去不能配对字符的个数再加1
# 怎么找出不能配对的字符有多少个还是有点技巧的,可以认真体会下代码
if len(s) == 0:
return 0
hash = {}
for c in s:
if c in hash:
del hash[c]
else:
hash[c] = True
remove = len(hash)
if remove > 0:
remove = remove - 1
return len(s) - remove
二刷
思路、解法和一刷是一样。这个解法还是挺精巧的,不知道还有没有别的解法。
三刷,很有必要
class Solution:
"""
@param s: a string which consists of lowercase or uppercase letters
@return: the length of the longest palindromes that can be built
"""
def longestPalindrome(self, s):
# write your code here
# 初看时没有思路,然后发现可以统计字符出现的次数
# 但是仍然不知道具体怎么实现
# 看了答案后,觉得思路非常精巧,但是难以想出来
# 统计不能构成回文串的字符的数量
# 但是这个解法确实不易被想出来
# 接下来给一个比较直接的解法
# 记录每个字符出现的次数,如果为偶数次,全部加到总长度
# 如果为奇数次,加到总长度。这个时候总长度就变为奇数了
# 后续的奇数次,就减去1,然后再加到总长度
import collections
count = collections.Counter(s)
res = 0
for val in count.values():
if val % 2 == 0:
res += val
else:
if res % 2 == 0:
res += val
else:
res += (val - 1)
return res
13. 字符串查找
对于一个给定的 source 字符串和一个 target 字符串,你应该在 source 字符串中找出 target 字符串出现的第一个位置(从0开始)。如果不存在,则返回 -1。
class Solution:
"""
@param source:
@param target:
@return: return the index
"""
def strStr(self, source, target):
# Write your code here
# 这个题目帮我复习了字符串相关的知识,切片,比较,
# find方法,upper方法,遍历,长度
# version 1
# 遍历source字符串,看是否存在字串和target相同
# len_s = len(source)
# len_t = len(target)
# for i in range(len_s - len_t + 1):
# if source[i:i + len_t] == target:
# return i
# return -1
# version 2
# 使用字符串方法 find
return source.find(target)
二刷
思路和解法和一刷一样
415. 有效回文串
给定一个字符串,判断其是否为一个回文串。只考虑字母和数字,忽略大小写。
class Solution:
"""
@param s: A string
@return: Whether the string is a valid palindrome
"""
def isPalindrome(self, s):
# write your code here
# 首先是知晓回文串的定义,已知晓
# 其次看清题目中说的只考虑字母和数字,忽略大小写
# 帮我掌握字符串方法,isalnum()是否只含有字母或数字,isalpha()是否只含有字母,
# isdigit()是否只含有数字,s.lower()转为小写字母
# 使用两根指针从两边到中间遍历整个字符串,
# 遇到不同的字符就表明不是回文串,返回false
start = 0
end = len(s) - 1
s = s.lower()
while start < end:
if start < end and s[start].isalnum() and s[end].isalnum():
if s[start] != s[end]:
return False
start += 1
end -= 1
if start < end and not s[start].isalnum() and s[end].isalnum():
start += 1
if start < end and s[start].isalnum() and not s[end].isalnum():
end -= 1
if start < end and not s[start].isalnum() and not s[end].isalnum():
start += 1
end -= 1
return True
二刷,代码更简洁一些
class Solution:
"""
@param s: A string
@return: Whether the string is a valid palindrome
"""
def isPalindrome(self, s):
# write your code here
# 不占用额外空间,
# 采用双指针,一头一尾
i, j = 0, len(s) - 1
while i < j:
while i < j and not s[i].isalnum():
i += 1
while i < j and not s[j].isalnum():
j -= 1
while i < j and s[i].lower() != s[j].lower():
return False
i += 1
j -= 1
return True
200. 最长回文子串
给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串。
class Solution:
"""
@param s: input string
@return: a string as the longest palindromic substring
"""
def longestPalindrome(self, s):
# write your code here
# 刚看到题目时感觉是动规题目,想用动规来做,但是没能实现
# 答案采用的是基于中心线的枚举,感觉也非常好
# 尝试用答案的解法自己实现一遍
length = len(s)
if length == 0:
return ''
longest = 0
for i in range(length):
sub = self.findPalindrome(s, i, i)
if longest < len(sub):
longest = len(sub)
res = sub
sub = self.findPalindrome(s, i, i + 1)
if longest < len(sub):
longest = len(sub)
res = sub
return res
def findPalindrome(self, s, left, right):
while left >= 0 and right <= len(s) - 1:
if s[left] != s[right]:
break
left = left - 1
right = right + 1
return s[left + 1:right]
二刷,掌握的不够好
667. 最长的回文序列
给一字符串 s, 找出在 s 中的最长回文子序列的长度. 你可以假设 s 的最大长度为 1000.
class Solution:
"""
@param s: the maximum length of s is 1000
@return: the longest palindromic subsequence's length
"""
def longestPalindromeSubseq(self, s):
# write your code here
# 这个题目看着和627 最长的回文串类似,但是实际上是不同的
# 差异在于子序列的定义,子序列不同于子串,但也是不能改变字符次序的
# 没说是不是大小写敏感,那就默认是敏感的
# 不会做,看了答案后,觉得也挺简单的
# dp[i][j]表示字符i到j的最长回文子序列
# 如果首尾字符相同,dp[i][j]等于去掉首尾字符后的字符串的最长回文子序列加2
# 如果首尾字符不同,dp[i][j]等于
# 去掉首字符的字符串的最长回文子序列和去掉尾字符的字符串的最长回文子序列的较大值
length = len(s)
if length == 0:
return 0
dp = [[0] * length for _ in range(length)]
for i in range(length - 1, -1, -1):
dp[i][i] = 1
for j in range(i + 1, length):
if s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1] + 2
if s[i] != s[j]:
dp[i][j] = max(dp[i][j - 1], dp[i + 1][j])
return dp[0][length - 1]