字符串算法总结

字符串算法总结

替换空格(没什么好说的,白给题)

class Solution:
    # s 源字符串
    def replaceSpace(self, s):
        # write code here
        l = len(s.split(' '))
        a = ''
        for i in range(l-1):
            a += s.split(' ')[i] + '%20'
        a = a+s.split(' ')[l-1]
        return a

字符串的全排列

class Solution:
    def Permutation(self, ss):
        if len(ss) <= 1:
            return ss
        res = set()
        # 遍历字符串,固定第一个元素,第一个元素可以取a,b,c...,然后递归求解
        for i in range(len(ss)):
            for j in self.Permutation(ss[:i] + ss[i+1:]): # 依次固定了元素,其他的全排列(递归求解)
                res.add(ss[i] + j) # 集合添加元素的方法add(),集合添加去重(若存在重复字符,排列后会存在相同,如baa,baa)
        return sorted(res)         # sorted()能对可迭代对象进行排序,结果返回一个新的list
#DFS全排列加去重
class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        self.result = []
        size = len(nums)
        def dfs(res):
            if len(res)==size:
                self.result.append(res[:])
                return
            for i in range(len(nums)):
                #去掉相邻重复元素数组
                if i>0 and nums[i]==nums[i-1] and not list1[i-1]:
                    continue
                if list1[i]:
                    continue
                 #是否选用,建立标志位
                list1[i] = True
                res.append(nums[i])
                dfs(res)
                list1[i] = False
                res.pop()
        list1 = [False for _ in range(len(nums))]
        nums.sort()
        dfs([])
        return self.result


第一次只出现一次的字符(哈希)

class Solution:
    def FirstNotRepeatingChar(self, s):
        # write code here

        ls=[0]*256
        #遍历字符串,下标为ASCII值,值为次数
        for i in s:
            ls[ord(i)]+=1
        #遍历列表,找到出现次数为1的字符并输出位置
        for j in s:
            if ls[ord(j)]==1:
                return s.index(j)
        return -1

左旋字符串(两次翻转)

# -*- coding:utf-8 -*-
class Solution:
 
    def reverse(self, s):
        if not s:
            return ""
 
        length = len(s)
        if length <= 0:
            return ""
 
        s = list(s)
        #print s
        start = 0
        end = length - 1
        while start < end:
            s[start], s[end] = s[end], s[start]
            start += 1
            end -= 1
        #print 'after', s
        return ''.join(s)
     
 
    def LeftRotateString(self, s, n):
        # write code here
        if not s:
            return ""
        length = len(s)
        if length <= 0:
            return ""
        if n > length:
            n = n % length
 
        s = self.reverse(s)
 
        first = ""
        second = ""
        for i in range(length - n):
            first += s[i]
        first = self.reverse(first)
        for i in range(length - n, length, 1):
            second += s[i]
        second = self.reverse(second)
        return first + second
            

判断字符串是否为合法数字

class Solution:
    def StrToInt(self, s):
        # write code here
        # 先排除异常特殊情况
        if s in ['','-','+','+-','-+']:
            return 0
        count = 0
        # 只要有非法字符就不过
        for i in s:
            # 检查字母
            if i not in '0123456789+-':
                count += 1
        # 只要-+号不在第一位就不过
        for i in s[1:]:
            if i not in '0123456789':
                count += 1
        if count:
            return 0
        return int(s)

最小覆盖子串

from collections import defaultdict
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        count_s = defaultdict(int)
        count_t = defaultdict(int)
        for x in t:
            count_t[x] +=1
        left = 0
        valid = 0
        start = -1
        minlen = float(inf)
        for right in range(len(s)):
            x = s[right]
            if x in count_t:
                count_s[x] +=1 
                if count_s[x] == count_t[x]:
                    valid +=1
            while valid == len(count_t):
                if right - left<minlen:
                    minlen = right-left
                    start = left
                l = s[left]
                left +=1
                if l in count_s:
                    count_s[l] -=1
                    if count_s[l] < count_t[l]:
                        valid -=1
        if start == -1:
            return ''
        return s[start:start+minlen+1]

表示数值的字符串

class Solution:
    # s字符串
    def isNumeric(self, s):
        # write code here
        if len(s) <= 0:
            return False
        # 分别标记是否出现过正负号、小数点、e,因为这几个需要特殊考虑
        has_sign = False
        has_point = False
        has_e = False
        for i in range(len(s)):
            # 对于e的情况
            if s[i] == 'E' or s[i] == 'e':
                # 不同出现两个e
                if has_e:
                    return False
                # e不能出现在最后面,因为e后面要接数字
                else:
                    has_e = True
                    if i == len(s) -1:
                        return False   
            # 对于符号位的情况
            elif s[i] == '+' or s[i] == '-':
                # 如果前面已经出现过了符号位,那么这个符号位,必须是跟在e后面的
                if has_sign:
                    if s[i-1] != 'e' and s[i-1] != 'E':
                        return False
                # 如果这是第一次出现符号位,而且出现的位置不是字符串第一个位置,那么就只能出现在e后面
                else:
                    has_sign = True
                    if i > 0 and s[i-1] != 'e' and s[i-1] != 'E':
                        return False
            # 对于小数点的情况
            elif s[i] == '.':
                # 小数点不能出现两次;而且如果已经出现过e了,那么就不能再出现小数点,因为e后面只能是整数
                if has_point or has_e:
                    return False
                # 如果是第一次出现小数点,如果前面出现过e,那么还是不能出现小数点
                else:
                    has_point = True
                    if i > 0 and (s[i-1] == 'e' or s[i-1] == 'E'):
                        return False
            else:
                # 其他字符必须是‘0’到‘9’之间的
                if s[i] < '0' or s[i] > '9':
                    return False
        return True

单词接龙

from typing import List
from collections import deque

class Solution:
    def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
        word_set = set(wordList)
        if len(word_set) == 0 or endWord not in word_set:
            return 0

        if beginWord in word_set:
            word_set.remove(beginWord)
        #储存队列
        queue = deque()
        queue.append(beginWord)
        #防止重复
        visited = set(beginWord)
        visited.add(beginWord)

        step = 1
        while queue:
            current_size = len(queue)
            #queue中可能有多个与上一次迭代的单词相差一个编辑距离的单词
            for i in range(current_size):
                word = queue.popleft()

                word_list = list(word)
                for j in range(len(word_list)):
                    origin_char = word_list[j]
                    #扩散寻找
                    for k in range(26):
                        word_list[j] = chr(ord('a') + k)
                        next_word = ''.join(word_list)
                        if next_word in word_set:
                            #判断是否到达终点
                            if next_word == endWord:
                                return step + 1
                            if next_word not in visited:
                                queue.append(next_word)
                                word_set.remove(next_word)
                    #跟回溯一样返回原状态
                    word_list[j] = origin_char
            step += 1
        return 0

移掉K位数字

给定一个以字符串表示的非负整数num,移除这个数中的K位数字,使得最后剩下的数字最小。

class Solution:
    def removeKdigits(self, num: str, k: int) -> str:
        if not num or len(num)<=k:
            return '0'
        count = 0
        res = ''
        begin = 0
        max_len = len(num)-k
        #类似于滑动窗口的思想,最后剩下length-k个数字
        while count < max_len:
            min_index = 0
            min_num = float('inf')
            #每K个长度的窗口选一个最小的数字
            for i in range(begin,k+count+1):
                if int(num[i])<min_num:
                    min_index = i
                    min_num = int(num[i])
            res +=str(min_num)
            begin = min_index+1
            count +=1
        return str(int(res))

字符串的排列

字符串的全排列

import collections
class Solution(object):
    def checkInclusion(self, s1, s2):
        """
        :type s1: str
        :type s2: str
        :rtype: bool
        """
        l1, l2 = len(s1), len(s2)
        c1 = collections.Counter(s1)
        c2 = collections.Counter()
        cnt = 0 #统计变量,全部26个字符,频率相同的个数,当cnt==s1字母的个数的时候,就是全部符合题意,返回真
        p = q = 0 #滑动窗口[p,q]
        while q < l2:
            c2[s2[q]] += 1
            if c1[s2[q]] == c2[s2[q]]: #对于遍历到的字母,如果出现次数相同
                cnt += 1               #统计变量+1
            if cnt == len(c1):         #判断结果写在前面,此时证明s2滑动窗口和s1全部字符相同,返回真
                return True
            q += 1                     #滑动窗口右移
            if q - p + 1 > l1:         #这是构造第一个滑动窗口的特殊判断,里面内容是维护边界滑动窗口
                if c1[s2[p]] == c2[s2[p]]:    #判断性的if写在前面,因为一旦频率变化,这个统计变量就减1
                    cnt -= 1
                c2[s2[p]] -= 1                #字典哈希表移除最前面的字符
                if c2[s2[p]] == 0:            #由于counter特性,如果value为0,必须删除它
                    del c2[s2[p]]
                p += 1                        #最前面的下标右移动
        return False

KMP字符串的排列

'''
字符串匹配
'''
def KMP(pat):
    x = 0
    for i in range(m):
        for c in range(256):
            if c == ord(pat[i]):   
                dp[i][c] = i+1
            else:
                dp[i][c] = dp[x][c]
        x = dp[x][ord(pat[i])]

def search(txt):
    n = len(txt)

    j = 0
    for i in range(n):
        j = dp[j][ord(txt[i])]
        if (j==m):
            return (i-m+1)
    return -1

if __name__ == "__main__":
    pat = 'aaab'
    txt = 'aaacaaab'
    m = len(pat)
    dp = [[0]*256 for _ in range(m)]
    dp[0][0] = 1
    KMP(pat)
    print(search(txt))

无重复字符的最长子串

'''
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

'''
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if not s:
            return 0
        left = 0
        right = 0
        n = len(s)
        max_list = []
        res = 0
        for i in range(n):
            if s[i] not in max_list:
                max_list.append(s[i])
                right += 1
            else:
                max_list.append(s[i])
                while max_list[0] != s[i]:
                    max_list.pop(0)
                    left += 1
                max_list.pop(0)
                left += 1
            res = max(res,len(max_list))
        return res


a = Solution()
s = "abcabcbb"
print(a.lengthOfLongestSubstring(s))

字符串转换整数

'''
请你来实现一个 atoi 函数,使其能将字符串转换成整数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。接下来的转化规则如下:

如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。
假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。
该字符串在有效的整数部分之后也可能会存在多余的字符,那么这些字符可以被忽略,它们对函数不应该造成影响。

'''
import re
class Solution:
    def myAtoi(self, str: str) -> int:
        INT_MAX = 2147483647
        INT_MIN = -2147483648
        str = str.lstrip()      #清除左边多余的空格
        #正则匹配  ^代表匹配开头 [\+\-\s] 代表匹配+-空白  ?代表匹配一个或0个 \d+代表匹配多个数字
        num_re = re.compile(r'^[\+\-\s]?\d+')   #设置正则规则
        num = num_re.findall(str)   #查找匹配的内容
        num = int(*num) #由于返回的是个列表,解包并且转换成整数
        return max(min(num,INT_MAX),INT_MIN)    #返回值
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值