今天是本菜鸟第一天刷leetcode,碰巧昨天的“每日一题”我点进去是回文数有关的,作为新手甚至提到回文数大脑一片空白,所以决定从题库里找找回文数相关的简单级题目热热身。
首先注意python实现字符串倒序非常简单,下面代码表示的就是b是a的倒序字符串:
a = str(a)
b = a[::-1]
而回文数意思就是一个字符串(可以是数字也可以是字母组成)正序和倒序一样。那么直接来个判断就可以知道这个字符串是不是回文数了
a = str(a)
b = a[::-1]
return b == a #在函数中返回true表示是回文数,返回false表示不是回文数
上面代码并不规范,只是表达了一个关于回文数用python最基础的思路,下面看一看具体的题目吧!
面试题 01.04. 回文排列
给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一。
回文串是指正反两个方向都一样的单词或短语。排列是指字母的重新排列。
回文串不一定是字典当中的单词。
示例1:
输入:“tactcoa”
输出:true(排列有"tacocat"、“atcocta”,等等)
分析:首先要确定回文串的特点是什么?也就是什么样的字符串可以通过位置变化组成回文数?
1.全为偶数个字符组,例如 abba abccba
2.仅由一组奇数个的字符其余全为偶数个字符组成,例如 acbca cacac aaa
总结以上两种情况,只需要字符串中有0或1组奇数个字符,那么这个字符串就是回文数。
思路一:手动生成“字符-个数”关系的字典
class Solution:
def canPermutePalindrome(self, s: str) -> bool:
e_count = 0
x = list(s)
result = {}
for i in set(x):
result[i] = x.count(i)
for key in result:
if result[key] % 2 == 1:
e_count += 1
return e_count < 2
思路2:列表内元素计数Counter,返回字典,这是python库中的便捷工具。
class Solution:
def canPermutePalindrome(self, s: str) -> bool:
from collections import Counter
result = Counter(s)
count = []
for value in Counter(s).values():
if value%2 == 1:
count.append(value)
return len(count) <2
这样代码看起来又简洁了很多但这还不够python!!!
再来:
class Solution:
def canPermutePalindrome(self, s: str) -> bool:
count = [i for i in Counter(s).values() if i%2 == 1]
return len(count) <2
125. 验证回文串给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: “A man, a plan, a canal: Panama”
输出: true
示例 2:
输入: “race a car”
输出: false
这一题中字符串需要去掉空格、标点符号,并且英文字母大小写需要统一,提取出数字和字符的纯字符串。我凭借自己仅有的一点点知识,第一个想到了正则匹配!纯字符串判断回文就如本文一开头所讲的,看下面代码:
import re #自行百度查文档,正则匹配库
class Solution:
def isPalindrome(self, s: str) -> bool:
s = re.sub(r'[^a-z0-9]', '', s.strip().lower())#正则匹配,仅匹配出字母和数字,并统一转成小写
return s == s[::-1]
680. 验证回文字符串 Ⅱ给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。
示例 1:
输入: “aba”
输出: True
示例 2:
输入: “abca”
输出: True
解释: 你可以删除c字符。
注意:
字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。
这一题似乎更复杂了些,一开始打算遍历删除字符串中的每一个元素,分别判断他们是不是回文,可是最大长度50000呢,系统给我验证答案时直接就崩了。。。
class Solution:
def validPalindrome(self, s: str) -> bool:
c = 0
o = 0
for i in s:
a = s[:o]+s[o+1:]
o += 1
# a = s.replace(i, '', 1)
# print(a)
if a == a[::-1]:
c += 1
if c > 0:
return True
else:
return False
上面代码是错误答案,请勿模仿!!!
看了看题解,发现了个双指针法,听起来高大上,实际就是从最左边的索引和最右边的索引依次比较并向中间移动,对python来说只是个小操作:
class Solution:
def validPalindrome(self, s: str) -> bool:
if s == s[::-1]:
return True
i = 0
j = len(s)-1 # i和j就是双指针
while i < j:
if s[i] != s[j]:
b = s[:i]+s[i+1:]#字符串切片
c = s[:j]+s[j+1:]#字符串切片
return b == b[::-1] or c == c[::-1]
i = i+1
j = j-1
注意这里面还用到了python非常便捷的字符串切片功能。例如一个字符串s = “adca”,我们如果需要删除其中的字符c,只需要这样:
a = s[:2]+s[3:]
这样就得到了删除c之后的字符串a=“ada”
希望每天都能坚持刷一点题,欢迎各位大佬们来交流指正。尤其是算法的时间复杂度空间复杂度这块我还不怎么明白,欢迎大家来评论教教我,比心心!