Leetcode(6)——字符串

格式:

题号+题名+简单思路+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+ji+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 2numRows2为一个循环
    • 首行尾行只有一个起点;分别是 0 0 0 n u m R o w s − 1 numRows-1 numRows1
    • 中间的行有两个起点;分别是 i i i i + 2 ( n u m R o w s − i − 1 ) i+2(numRows-i-1) i+2(numRowsi1)
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)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值