leetcode 字符串

滑动窗口

连续字符串,双指针。

查看串中是否有串 leetcode 28

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

class Solution:
    def strStr(self,haystack,needle):
        start = 0
        for end in range(len(needle)-1,len(haystack)):
        #这里+1是因为前面已经把末尾包含进来了
            if needle == haystack[start:end+1]:
                return start
            start+=1
        return -1

字符串的排列 leetcode 567

给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。

示例:
输入: s1 = “ab” s2 = “eidbaooo”
输出: True
解释: s2 包含 s1 的排列之一 (“ba”).

from collections import Counter
class Solution:
    def checkInclusion(self, s1: str, s2: str) -> bool:
        target = Counter(s1)
        start = 0
        for end in range(len(s1)-1,len(s2)):
            if target == Counter(s2[start:end+1]):
                return True
            else:
                start+=1
        return False
  • 乍一看很难,很容易思维定式的想到全排列,问题是全排列这个复杂度相当高,得算到啥时候,可是其实并不是非要全排列的全部形式,只要知道每个对应的元素有几个就可以了
  • 只要引入collections Counter这个包,问题就很愉快的转化成28了。

最长不重复子串 leetcode 3

class Solution:
    def lengthOfLongestSubString(self,str):
        start = 0
        mark = set()
        max_length = float('-inf')
        for end in range(len(str)):
            while start<=end and str[end] in mark:
                mark.remove(str[start])
                start+=1
            mark.add(str[end])
            max_length = max(max_length,end-start+1)
        if max_length ==float('-inf'):
            return 0
        else:
           return max_length
  • 不定长。
  • 判断长度问题无需再初始化一个字符串,直接在原串上比较长度即可。
  • 先看看尾部在不在之内,如果在,满足字符串的约束,先删除头部,不在了之后才开始添加。
  • 都是先往里放,只不过是这个题目放不了,因为只能放不重复的,所以先判断,所以这里再次明确while有if的能力,是循环带上判断,不仅仅是for。

长度最短子数组 leetcode 209

找出连续和大于s的最短子数组

class Soultion:
	def minSubArrayLen(self,s,nums):
		start = 0 
		min_len = float('inf')
		cur_sum = 0
		for end in range(len(nums)):
			cur_sum+=nums[end]
			while cur_sum>=s:
				min_len = min(min_len,end-start+1)
				cur_sum-=nums[start]
				start+=1
		if min_len == float('inf'):
			return 0
		return min_len
		

水果成篮 leetcode 904

连续子数组中种类不大于2的最长序列长度是多少

class Solution:
    def totalFruit(self,tree):
        start = 0
        max_len = float('-inf')
        adict = dict()
        for end in range(len(tree)):
            if tree[end] not in adict:
                adict[tree[end]] = 1
            else:
                adict[tree[end]]+=1
            while len(adict)>2:
                adict[tree[start]]-=1
                if adict[tree[start]] == 0:
                    del adict[tree[start]]
                start+=1
            #这个判断写在哪里合适,有可能一直种类都没大于2,所以在while的外面
            max_len = max(max_len,end-start+1)
        if max_len == float('-inf'):
            return 0
        else:
            return max_len
  • 两个数据结构,一个是记录当前数字种类的dict。
  • 另一个是记录原字符串的起止位置。

lc 1248. 统计「优美子数组」

在这里插入图片描述

class Solution:
    def numberOfSubarrays(self, nums: List[int], k: int) -> int:
        def ltk(nums,k):
            start = 0
            odd_count = 0
            res = 0
            for end in range(len(nums)):
                if nums[end]%2==1:
                    odd_count+=1
                while odd_count>k:
                # 满足条件的减去
                    if nums[start]%2==1:
                        odd_count-=1
                # 满足与否都要往前走
                    start+=1
                # 即是跨度,又是个数,正好是组合数
                res += end-start+1
            return res
        return ltk(nums,k)-ltk(nums,k-1)
  • 连续恰好为

前缀和

列表中连续和为k的个数 leetcode 560

nums = [1,0,2,1] , k = 3
{0:1,1:2,3:1,4:1}

class Soultion:
	def subarraySum(self,nums,k):
		#因为前缀和是到该位置和的个数,所以初始化为0有1个肯定没错,后面还有0再追加即可
		adict = {0:1}
		cur_sum = 0
		count = 0
		for num in nums:
			cur_sum+=num
			if cur_sum-k in adict:
				count+=adict[cur_sum-k]
			if cur_sum in adict:
				adict[cur_sum]+=1
			else:
				adict[cur_sum]=1
		return count
  • 放在这个模块里因为也是有字符串连续的意思。
  • 这个题目相当于求pdf,然后每次找到差如果在list中则加上对应的数字为最后有的个数,twosum类似

最长和谐子序列 lc 594

在这里插入图片描述

class Solution:
    def findLHS(self, nums: List[int]) -> int:
        c = Counter(nums)
        res = 0
        for x in c:
            if x+1 in c:
                res = max(res,c[x]+c[x+1])
        return res
  • 仅仅是和上面的题长得有点像,但是没有连续的要求,所以就很简单,依次的往下找就可以。
  • 这个题目读起来非常迷惑,转成这样写不容易想到。

通过删除字母匹配到字典里最长单词 lc 524

输入:s = “abpcplea”, d = [“ale”,“apple”,“monkey”,“plea”]
输出: “apple”


# 比较好想,上面的解法需要记住之前的题目
class Solution:
    def findLongestWord(self, s: str, dictionary: List[str]) -> str:
        dictionary.sort(key = lambda x:(-len(x),x))
        for d in dictionary:
            start = 0
            for end in range(len(s)):
                if start<len(d) and d[start] == s[end]:
                    start+=1
                if start==len(d):
                    return d
        return ''
# 下面的代码废弃掉
class Solution:
    def findLongestWord(self, s: str, d: List[str]) -> str:
        # d.sort(key = lambda i:len(i),reverse=True) 
        #先按照长度长度一样再按照字典序
        d.sort(key=lambda x:(-len(x), x))
        def isSubseq(word, s):
            i = 0
            for c in s:
                if c == word[i]:
                    i += 1
                if i == len(word):
                    return True
            return False
        for word in d:
            if isSubseq(word, s):
                return word
        return ""

  • sort的二级排序,框架就是for的这段框架。
  • 涉及到字符串的是上面那个方法,让source字符串往后移动,当一样的时候让target+1,目标是target的长度到头就找到了。不太容易写的是让谁移动,让source一直移动,找到了target,t移动一下,直到t到了头。

同构字符串 lc 205

在这里插入图片描述

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        if len(s)!=len(t):
            return False
        return self.halfIsom(s,t) and self.halfIsom(t,s)

    def halfIsom(self,s,t):
        lookup = {}
        for i in range(len(s)):
            if s[i] not in lookup:
                lookup[s[i]] = t[i]
            elif lookup[s[i]]!=t[i]:
                return False
        return True
  • 比较自然的想到是dict,但是需要想到是遍历的形式去建设对应map,如果都通过就ok,不通过就false
  • 难点二是看实例,正反的map是不一样的,不要强求,不一样就不一样。

计数二进制子串 lc 696

给定一个字符串 s,计算具有相同数量 0 和 1 的非空(连续)子字符串的数量,并且这些子字符串中的所有 0 和所有 1 都是连续的。
输入: “00110011”
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。

class Solution:
    def countBinarySubstrings(self, s: str) -> int:
        res = 0
        for i in range(len(s)-1):
            if int(s[i])+int(s[i+1])==1:
                index = 0
                while i>=index and i+1+index<len(s) and s[i]==s[i-index] and s[i+1]==s[i+1+index]:
                    index+=1
                    res+=1
        return res

# 以下的想法很奇特废弃掉
class Solution:
    def countBinarySubstrings(self, s: str) -> int:
        if len(s)<2:
            return 0
        nums = []
        tmp = s[0]
        #最先开始这是0
        count = 0
        for i in s:
            if i==tmp:
                count+=1
            else:
                nums.append(count)
                tmp=i
                #有一次之后这是1,这样就穿起来了
                count=1
        nums.append(count)
        ans = 0
        for i in range(len(nums)-1):
            ans+=min(nums[i],nums[i+1])
        return ans
- 和nlp常用方法类似,交换角色,移动指针。
- ==解法很巧妙依次的往后面取,两两的取小的即是他们的交集。==
- 可以这样也是后无效性,因为必须要仅仅贴在一起。
  • 先找到分裂点,**分裂开只需要保证两边的持续一样就可以,所以再加一个指针。**也是常用技巧之一。
  • 这样的计数不是+1就是res+=res+1

字符串转数字 lc 8

在这里插入图片描述

class Solution(object):
    def myAtoi(self, s):
        """
        :type s: str
        :rtype: int
        """
        s = s.lstrip()
        if not s:
            return 0
        sign = -1 if s[0] == "-" else 1
        if sign == -1 or s[0] == "+":
            s = s[1:]
        d = 0
        for i in s:
            if i.isdigit():
                d *= 10
                d += ord(i) - 48
            else:
                break
        # 在小里求大,大里求小
        return max(-2**31, min(sign * d,2**31-1))

#舍弃下面的解法,实在是太乱了,这个题目本身就非常的乱
class Solution:
    def myAtoi(self, s: str) -> int:
        stripS = s.strip()
        #如果只有一个'+'没数字后面又group不到
        if stripS == '' or stripS=='-' or stripS=='+':
            return 0
        #补充去除不能满足的模式
        s1 = re.match('[^\d]+',stripS.lstrip('-').strip('+'))
        if s1!=None:
            return 0
        else:
        #核心,但是也只能找到这样一种模式
            s1 = re.search('\-*\+*\d+',stripS).group()
        if s1[0:2]=='--' or s1[0:2]=='-+' or s1[0:2]=='++':
            return 0
        result = int(s1)
        if result>0:
            return 2**31-1 if result> 2**31-1 else result
        else:
            return -2**31 if result<-2**31 else result
  • 数字前面有0还原正常数字的方法如上d=d*10,d+=s[i]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值