格式:
题号+题名+简单思路+code
T5: 最长回文子串
- 遍历每一个(i,j)中心的回文子串的长度
class Solution:
def longestPalindrome(self, s: str) -> str:
self.s=s
ans=""
for i in range(len(s)):
s1=self.findPalindrome(i,i)
s2=self.findPalindrome(i,i+1)
ans=s1 if len(s1)>len(ans) else ans
ans=s2 if len(s2)>len(ans) else ans
return ans
def findPalindrome(self, l: int, r: int) -> str:
while l>=0 and r<=len(self.s)-1 and self.s[l]==self.s[r]:
l-=1;r+=1
return self.s[l+1:r]
滑动窗口解决子串问题
※T76: 最小覆盖子串
求出字符串s中能包括字符串t所有字母的最小子串
- 遍历以s中每一个位置起始能包括t中所有字母的最小子串
func minWindow(s string, t string) string {
ans:=""
curr:=1<<31-1
map_t:=map[byte]int{}
map_s:=map[byte]int{}
for i := range t {
map_t[t[i]]++
}
left:=0
right:=0
match:=0
for right < len(s) {
if count, ok:=map_t[s[right]];ok {
map_s[s[right]]++
if map_s[s[right]]==count {
match++
}
}
right++
for match==len(map_t) {
if right-left<curr {
curr=right-left
ans=s[left:right]
}
if count, ok:=map_t[s[left]];ok {
map_s[s[left]]--
if count>map_s[s[left]] {
match--
}
}
left++
}
}
return ans
}
T438: 找到字符串中所有字母异位词
- 与T76框架相同;本题找长度与p相同的子串
func findAnagrams(s string, p string) []int {
ans:=[]int{}
map_s:=make(map[byte]int,0)
map_p:=make(map[byte]int,0)
for i := range p {
map_p[p[i]]++
}
match:=0
left:=0
right:=0
for right<len(s) {
if count,ok:=map_p[s[right]];ok {
map_s[s[right]]++
if count==map_s[s[right]] {
match++
}
}
right++
for match==len(map_p) {
if right-left==len(p) {
ans=append(ans,left)
}
if count,ok:=map_p[s[left]];ok {
map_s[s[left]]--
if count>map_s[s[left]] {
match--
}
}
left++
}
}
return ans
}
※T3: 无重复字符的最长子串
- 使用memo记录窗口中字符出现次数
- 向右移动right
- 当出现重复字符时,右移left缩小窗口
- 最长子串,在右移right时更新;
func lengthOfLongestSubstring(s string) int {
memo:=map[byte]int{}
left:=0
right:=0
ans:=0
for right<len(s) {
memo[s[right]]++
if memo[s[right]]==1 && right-left+1>ans {
ans=right-left+1
}
for memo[s[right]]>1 && left<right {
memo[s[left]]--
left++
}
right++
}
return ans
}
T227: 基本计算器Ⅱ
- 加减乘除→栈
- 字符串转整数→
n=n*10+int(c-'0')
c-'0'是int32类型,所以要强制转换
import "unicode"
func calculate(s string) int {
stack:=[]int{}
sign:='+'
num:=0
for idx,c:=range s {
if unicode.IsNumber(c) {
num=num*10+int(c-'0')
}
if (!unicode.IsSpace(c) && !unicode.IsNumber(c)) || idx==len(s)-1 {
switch sign {
case '+':
stack=append(stack,num)
case '-':
stack=append(stack,-num)
case '*':
stack[len(stack)-1]=stack[len(stack)-1]*num
case '/':
stack[len(stack)-1]=stack[len(stack)-1]/num
}
sign=c
num=0
}
}
ans:=0
for _,i := range stack {
ans+=i
}
return ans
}
※T224: 基本计算器
import "unicode"
func calculate(s string) int {
seq:=[]rune(s)
idx:=0
return calculateAssist(seq, &idx)
}
func calculateAssist(seq []rune, idx *int) int {
num:=0
sign:='+'
ans:=0
stack:=[]int{}
for *idx<len(seq) {
c:=seq[*idx]
if unicode.IsNumber(c) {
num=num*10+int(c-'0')
} else if c=='(' {
(*idx)++
num=calculateAssist(seq, idx)
} else if !unicode.IsSpace(c) { // 运算符或者')'
if c==')' {
break
}
switch sign {
case '+':
stack=append(stack, num)
case '-':
stack=append(stack, -num)
case '*':
stack[len(stack)-1]*=num
case '/':
stack[len(stack)-1]/=num
}
sign=c
num=0
}
(*idx)++
}
switch sign { // 末尾数字
case '+':
stack=append(stack, num)
case '-':
stack=append(stack, -num)
case '*':
stack[len(stack)-1]*=num
case '/':
stack[len(stack)-1]/=num
}
for i:=0;i<len(stack);i++ {
ans+=stack[i]
}
return ans
}
※T43: 字符串相乘
- 将乘数拆分,加入对应的
i+j
和i+j+1
位置 '3'
和3
的互相转化;int('3' - '0') = 3;byte(3)+'0'='3'(byte)
func multiply(num1 string, num2 string) string {
res:=make([]int,len(num1)+len(num2))
for i:=len(num1)-1;i>=0;i-- {
for j:=len(num2)-1;j>=0;j-- {
tmp:=int(num1[i]-'0')*int(num2[j]-'0')
tmp+=res[i+j+1]
res[i+j+1]=tmp%10
res[i+j]+=tmp/10
}
}
index:=0
for ;index<len(res);index++ {
if res[index]!=0 {
break
}
}
ans:=make([]byte,len(res)-index)
for i,v := range res[index:] {
ans[i]=byte(v)+'0'
}
result:=string(ans)
if len(result)==0 {
return "0"
} else {
return result
}
}
T6: Z字形变换
- 规律:
- 以 2 n u m R o w s − 2 2numRows-2 2numRows−2为一个循环
- 首行尾行只有一个起点;分别是 0 0 0和 n u m R o w s − 1 numRows-1 numRows−1
- 中间的行有两个起点;分别是 i i i和 i + 2 ( n u m R o w s − i − 1 ) i+2(numRows-i-1) i+2(numRows−i−1)
func convert(s string, numRows int) string {
if numRows<=1 {
return s
}
ans:=make([]byte, len(s))
idx:=0
for i:=0;i<numRows;i++ {
if i==0 || i==numRows-1 {
start:=i
for start<len(s) {
ans[idx]=s[start]
idx++
start+=2*numRows-2
}
} else {
s1:=i
s2:=s1+(numRows-1-s1)*2
for s1<len(s) {
ans[idx]=s[s1]
idx++
s1+=2*numRows-2
if s2<len(s) {
ans[idx]=s[s2]
idx++
s2+=2*numRows-2
}
}
}
}
return string(ans)
}
T38: 外观数列
- 预计算
class NumArrays:
def __init__(self):
self.nums=["1"]
for i in range(1, 30):
prev=self.nums[i-1]
tmp=""
c=prev[0]
count=1
for k in range(1, len(prev)):
if prev[k]==c:
count+=1
else:
tmp+=str(count)+c
c=prev[k]
count=1
tmp+=str(count)+c
self.nums.append(tmp)
def getValue(self, n):
return self.nums[n-1]
class Solution:
array=NumArrays()
def countAndSay(self, n: int) -> str:
return self.array.getValue(n)
T14: 最长公共前缀
- 递归写法
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if len(strs)==0:
return ""
return strs[0][:self.longestCommonPrefixAssit(strs, 0)]
def longestCommonPrefixAssit(self, strs, idx) -> int:
if idx==len(strs[0]):
return 0
c=strs[0][idx]
for i in range(1, len(strs)):
if idx==len(strs[i]) or strs[i][idx]!=c:
return 0
return 1+self.longestCommonPrefixAssit(strs, idx+1)
T67: 二进制求和
- 类似合并两个有序数组
- 类似的有T415字符串相加(十进制)
class Solution:
def addBinary(self, a: str, b: str) -> str:
tmp=[]
idx1=len(a)-1
idx2=len(b)-1
flag=0
while idx1>=0 or idx2>=0:
if idx1==-1:
tmp.append(str((int(b[idx2])+flag)%2))
flag=(int(b[idx2])+flag)//2
idx2-=1
elif idx2==-1:
tmp.append(str((int(a[idx1])+flag)%2))
flag=(int(a[idx1])+flag)//2
idx1-=1
else:
tmp.append(str((int(a[idx1])+int(b[idx2])+flag)%2))
flag=(int(a[idx1])+int(b[idx2])+flag)//2
idx1-=1
idx2-=1
if flag==1:
tmp.append("1")
return "".join(list(reversed(tmp)))
剑指50: 第一个只出现一次的字符
- python3.6之后字典的键就是按照插入顺序排序的
- 否则使用OrderedDict,也是按照插入顺序排序
class Solution:
def firstUniqChar(self, s: str) -> str:
memo=collections.OrderedDict()
for ss in s:
memo.setdefault(ss, 0)
memo[ss]+=1
for ss in memo:
if memo[ss]==1:
return ss
return " "
剑指58: 翻转单词顺序
- 给出单词的开头和结尾坐标
class Solution:
def reverseWords(self, s: str) -> str:
stack=[]
start=0
end=0
for idx,ss in enumerate(s):
if ss!=" ":
if idx==0 or s[idx-1]==" ":
start=idx
if idx==len(s)-1 or s[idx+1]==" ":
end=idx
stack.append(s[start:end+1])
return " ".join(reversed(stack))
剑指67: 字符串转整数
- 整型溢出问题;设置int64作为存储变量,在迭代过程中如果正数超出1<<31-1则判断溢出,负数绝对值超出1<<31则判断溢出
func strToInt(str string) int {
var ans int64=0
var flag int64=0
i:=0
for i<len(str) && str[i]==' ' {
i++
}
if i==len(str) {
return 0
}
b:=str[i]
switch {
case b=='+':
flag=1
i++
case b=='-':
flag=-1
i++
case b>='0' && b<='9':
flag=1
default:
return 0
}
for i<len(str) && str[i]>='0' && str[i]<='9' {
ans=ans*10+int64(str[i]-'0')
if ans>1<<31-1 && flag==1 {
return 1<<31-1
}
if ans>1<<31 && flag==-1 {
return -(1<<31)
}
i++
}
return int(ans*flag)
}