单词拆分

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:

输入: s = “leetcode”, wordDict = [“leet”, “code”]
输出: true
解释: 返回 true 因为 “leetcode” 可以被拆分成 “leet code”。
示例 2:

输入: s = “applepenapple”, wordDict = [“apple”, “pen”]
输出: true
解释: 返回 true 因为 “applepenapple” 可以被拆分成 “apple pen apple”。
注意你可以重复使用字典中的单词。
示例 3:

输入: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
输出: false

动态规划的思路。(递归会超时)
将问题拆分成更小的子问题。用dp[i]表示0到i的子字符串是否可以拆分成满足条件的单词,在计算dp[i]的时候,只需要判断dp[i-len(word)]是否是true,如果是,那么dp[i]就是true。

class Solution(object):def wordBreak(self, s, wordDict):""":type s: str:type wordDict: List[str]:rtype: bool"""len_s = len(s)dp = [False for i in range(len_s+1)]dp[0] = Truefor i in range(1, len_s+1):for word in wordDict:if i>=len(word) and dp[i-len(word)] and word == s[i-len(word):i]:dp[i] = Truereturn dp[-1]

单词拆分 II

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。

说明:

分隔时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。

示例 1:输入:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
输出:
["cats and dog","cat sand dog"
]示例 2:输入:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
输出:
["pine apple pen apple","pineapple pen apple","pine applepen apple"
]
解释: 注意你可以重复使用字典中的单词。示例 3:输入:
s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
输出:
[]

解法:这次只能用递归,不能用动态规划了;
遍历wordDict中的每一个word,查看字符串s是否是由word开头的,即word是否是s的前缀;
若是,就将改word存储在结果中,并将s去掉这个word前缀,再进行第1步;
因为会出现很多重复搜索的过程,可以利用字典memo来保存,{’sanddog’:[‘sand dog’, ‘s and dog’]},遇到已经出现过的情况,直接查字典即可,速度会快很多。

class Solution(object):def wordBreak(self, s, wordDict):""":type s: str:type wordDict: List[str]:rtype: List[str]"""def dfs(s, wordDict, memo):if s in memo:return memo[s]if not s:return []res = []for word in wordDict:if s[:len(word)] != word:continueif len(s) == len(word):res.append(word)else:rest=dfs(s[len(word):], wordDict, memo)for item in rest:item = word + ' ' + itemres.append(item)memo[s]=resreturn resreturn dfs(s,wordDict,{})

Substring with Concatenation of All Words

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.

Example 1:Input:s = "barfoothefoobarman",words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.Example 2:Input:s = "wordgoodgoodgoodbestword",words = ["word","good","best","word"]
Output: []

题干中提到了每个单词都是等长的,所以可以对s中每lw个字符判断一下是否在words的字典里面
判断concatenation的时候就可以用while循环,两个break的条件:
第一个是使用tmp字典存储下每个单词出现的次数,如果substring中出现的单词不止一次就退出;
第二个是如果某单词不存在于字典中就退出。
注意整体上循环的次数应该是ls + 1 - lw*num次,也就是最多能有多少个substring的起始位置

class Solution(object):def findSubstring(self, s, words):""":type s: str:type words: List[str]:rtype: List[int]"""if s=="" or words == []:return []dic = {}num = len(words)for i in words:if i not in dic:dic[i] = 1else:dic[i] += 1tmp = words[0]lw = len(tmp)ls = len(s)res = []for i in range(ls + 1 - lw*num):tmp = {}j=0while j < num:w = s[i+j*lw:i+(j+1)*lw]if w not in dic:breakif w not in tmp:tmp[w] = 1else:tmp[w] += 1if tmp[w] > dic[w]:breakj+=1if j == num:res.append(i)return res

有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

示例 1:

输入: s = “anagram”, t = “nagaram”
输出: true
示例 2:

输入: s = “rat”, t = “car”
输出: false
说明:
你可以假设字符串只包含小写字母。

进阶:
如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

解法:
字母异位词指字母相同,但排列不同的字符串。
两种方案:第一个是使用字典存储s中每个字母的个数,再去判断t中字母个数是否相同即可;
第二个是直接将两个字符串排序后看是否相同,非常简单

class Solution(object):def isAnagram(self, s, t):""":type s: str:type t: str:rtype: bool"""return sorted(s) == sorted(t)

字母异位词分组

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
输出:
[
[“ate”,“eat”,“tea”],
[“nat”,“tan”],
[“bat”]
]
说明:

所有输入均为小写字母。
不考虑答案输出的顺序。

解法
同上,还是两种方案;
灵活使用tuple, dict等结构

class Solution(object):def groupAnagrams(self, strs):ans = collections.defaultdict(list)for s in strs:ans[tuple(sorted(s))].append(s)return ans.values()
class Solution:def groupAnagrams(strs):ans = collections.defaultdict(list)for s in strs:count = [0] * 26for c in s:count[ord(c) - ord('a')] += 1ans[tuple(count)].append(s)return ans.values()

同构字符串

给定两个字符串 s 和 t,判断它们是否是同构的。

如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。

所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。

示例 1:

输入: s = “egg”, t = “add”
输出: true
示例 2:

输入: s = “foo”, t = “bar”
输出: false
示例 3:

输入: s = “paper”, t = “title”
输出: true
说明:
你可以假设 s 和 t 具有相同的长度。

解法
用字典存储单词的映射关系即可。但是需要注意用两个词典,因为不管要让s映射到t,t也要能映射到s

class Solution(object):def isIsomorphic(self, s, t):""":type s: str:type t: str:rtype: bool"""dic1, dic2 = {}, {}n = len(s)for i in range(n):char_s, char_t = s[i], t[i]if char_s not in dic1:dic1[char_s] = char_telif dic1[char_s] != char_t:return Falseif char_t not in dic2:dic2[char_t] = char_selif dic2[char_t] != char_s:return Falsereturn True

字符串中的第一个唯一字符

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

案例:

s = “leetcode”
返回 0.

s = “loveleetcode”,
返回 2.

注意事项:您可以假定该字符串只包含小写字母。

解法
比较简单的题目,考察字典的应用。O(2n)比O(n)好得多;
记一下collections.Counter(s)的方法

本来以为会有优雅点的解法,但发现就是直接哈希。第一遍哈希得到字符次数,第二遍找到第一个位置

class Solution(object):def firstUniqChar(self, s):""":type s: str:rtype: int"""cnt = collections.Counter(s)for i in range(len(s)):tmp = s[i]if cnt[tmp] == 1:return ireturn -1
# -*- coding:utf-8 -*-
class Solution:def FirstNotRepeatingChar(self, s):# write code heredic = {}for x in s:if x not in dic:dic[x] = 0dic[x] += 1for i in range(len(s)):if dic[s[i]] == 1:return ireturn -1

反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:

输入:[“h”,“e”,“l”,“l”,“o”]
输出:[“o”,“l”,“l”,“e”,“h”]
示例 2:

输入:[“H”,“a”,“n”,“n”,“a”,“h”]
输出:[“h”,“a”,“n”,“n”,“a”,“H”]

解法:

  • 比较简单,因为是O(1)的,所以想到就是前后交换,直到中间即可
  • 采用异或的形式
class Solution(object):def reverseString(self, s):""":type s: List[str]:rtype: None Do not return anything, modify s in-place instead."""ll = len(s)for i in range(ll/2):s[i], s[ll-1-i] = s[ll-1-i], s[i]
def reverseStr(s):if not s:return sch = list(s)i , j = 0 , len(s)-1while i < j:ch[i] = chr(ord(ch[i]) ^ ord(ch[j]))ch[j] = chr(ord(ch[i]) ^ ord(ch[j]))ch[i] = chr(ord(ch[i]) ^ ord(ch[j]))# ch[i] = ch[i] ^ ch[j]  【错误的形式】# ch[j] = ch[i] ^ ch[j]# ch[i] = ch[i] ^ ch[j]i += 1j -= 1return "".join(ch)s = 'abcdef'
print(reverseStr(s))

翻转单词

给定一个字符类型的数组chas,请在单词间做逆序调整,只要做到单词顺序逆序即可,对空格的位置没有特别要求。例如把chas看成字符串为“I love you”,调整成“you love I”。

解法
首先对整个数组逆序,然后遍历数组找到每一个单词,将每个单词里的字符进行逆序即可。

#反转字符串
def reverseStr(s):if not s:return sch = list(s)i , j = 0 , len(s)-1while i < j:ch[i] = chr(ord(ch[i]) ^ ord(ch[j]))ch[j] = chr(ord(ch[i]) ^ ord(ch[j]))ch[i] = chr(ord(ch[i]) ^ ord(ch[j]))i += 1j -= 1return "".join(ch)#s = 'abcdef'
#print(reverseStr(s))#将句子反转,单词不反转。
def reverseWord(s):if not s:return srs = reverseStr(s)arr = rs.split(' ')res = []for a in arr:res.append(reverseStr(a))return ' '.join(res)s = 'I love dogs'
print(reverseWord(s))

验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

输入: “A man, a plan, a canal: Panama”
输出: true
示例 2:

输入: “race a car”
输出: false

解法

  • 用python自带的filter来做
  • 双指针法
class Solution:def isPalindrome(self, s: str) -> bool:s = list(filter(str.isalnum, s.lower()))return True if s == s[::-1] else False
class Solution:def isPalindrome(self, s):""":type s: str:rtype: bool"""n = len(s)i = 0j = n-1while i < j:if s[i].isalnum() == False:i += 1continueif s[j].isalnum() == False:j -= 1continueif s[i].lower() != s[j].lower():return Falsei += 1j -= 1return True

反转字符串中的元音字母

编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

示例 1:

输入: “hello”
输出: “holle”
示例 2:

输入: “leetcode”
输出: “leotcede”

解法
同样双指针方法

class Solution(object):def reverseVowels(self, s):""":type s: str:rtype: str"""letters = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']s2 = [x for x in s]l, r = 0, len(s2) - 1while l < r:while l < r and s2[l] not in letters:l += 1while l < r and s2[r] not in letters:r -= 1s2[l], s2[r] = s2[r], s2[l]l += 1r -= 1return ''.join(s2)

神奇的数字

题目描述
在这个特殊的假期里,由于牛牛在家特别无聊,于是他发明了一个小游戏,游戏规则为:将字符串数字中为偶数位的数字进行翻转,将翻转后的结果进行输出。

示例1
输入
“1234”
输出
“1432”
说明
第2、4位为偶数,所以将其翻转后,得到 1432

示例2
输入
“12346”
输出
“16342”
说明
第2、4、5位为偶数,所以将其翻转后,得到 16342

备注:
数字的长度<=10^7 且不包含数字0

解法
就是个双指针,一个从左往右,一个从右往左,遇到偶数就交换一下。

#
#
# @param number string字符串
# @return string字符串
#
class Solution:def change(self , number ):# write code hereif not number or len(number) == 1:return numbernums = [int(x) for x in number]i, j = 0, len(nums) - 1while i < j:while i < j and nums[i] % 2 == 1:i += 1while i < j and nums[j] % 2 == 1:j -= 1nums[i], nums[j] = nums[j], nums[i]i += 1j -= 1nums = [str(x) for x in nums]return ''.join(nums)

字符串距离计算

题目描述
给定两个长度相等的,由小写字母组成的字符串S1和S2,定义S1和S2的距离为两个字符串有多少个位置上的字母不相等。
现在牛牛可以选定两个字母X1和X2,将S1中的所有字母X1均替换成X2。(X1和X2可以相同)
牛牛希望知道执行一次替换之后,两个字符串的距离最少为多少。

示例1
输入
“aaa”,“bbb”
输出
0
说明
牛牛可以将S1中的字符’a’全部替换成字符’b’,这样S1就变成了"bbb",那么S1和S2的距离就是0

示例2
输入
“aabb”,“cdef”
输出
3
说明
一种可行的方案是将S1中的字符’a’全部替换成字符’c’,那么S1变成了"ccbb",和S2的距离是3

备注:

解法
参考标准题解:
对于所有可能的X1, X2, 记录cnt[X1][X2]有多少个位置i, 使得S1[i] == X1, S2[i] == X2
这一步只需扫描一遍字符串即可计算得到
然后枚举可能的X1, X2,这时距离 = 原本的距离 + cnt[X1][X1] - cnt[X1][X2]
时间复杂度O(N)

#
# 计算最少的距离
# @param S1 string字符串 第一个字符串
# @param S2 string字符串 第二个字符串
# @return int整型
#
class Solution:def GetMinDistance(self , S1 , S2 ):# write code herecnt = [[0 for i in range(26)] for j in range(26)]ans = 0for i in range(len(S1)):x, y = S1[i], S2[i]xx, yy = ord(x) - ord('a'), ord(y) - ord('a')cnt[xx][yy] += 1if xx != yy:ans += 1res = ansfor i in range(26):for j in range(26):res = min(res, ans + cnt[i][i] - cnt[i][j])return res

安置路灯

题目描述
小Q正在给一条长度为n的道路设计路灯安置方案。

为了让问题更简单,小Q把道路视为n个方格,需要照亮的地方用’.'表示, 不需要照亮的障碍物格子用’X’表示。

小Q现在要在道路上设置一些路灯, 对于安置在pos位置的路灯, 这盏路灯可以照亮pos - 1, pos, pos + 1这三个位置。

小Q希望能安置尽量少的路灯照亮所有’.'区域, 希望你能帮他计算一下最少需要多少盏路灯。

输入描述:
输入的第一行包含一个正整数t(1 <= t <= 1000), 表示测试用例数
接下来每两行一个测试数据, 第一行一个正整数n(1 <= n <= 1000),表示道路的长度。
第二行一个字符串s表示道路的构造,只包含’.‘和’X’。
输出描述:
对于每个测试用例, 输出一个正整数表示最少需要多少盏路灯。

示例1
输入
2
3
.X.
11
…XX…XX

输出
1
3

解法
比较简单的贪心算法,判断好边界条件即可


t = int(input().strip())
for _ in range(t):n = int(input().strip())s = input().strip()res = 0flag = 0for i in range(n):if flag == 0 and s[i] == '.':if i == n - 1:res += 1else:flag = 1elif flag == 1:res += 1flag = 2elif flag == 2:flag = 0print(res)

最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 “”。

示例 1:

输入: [“flower”,“flow”,“flight”]
输出: “fl”

示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。

说明:
所有输入只包含小写字母 a-z 。

解法
就是选出来一个,挨个从头到尾比较一下

class Solution(object):def longestCommonPrefix(self, strs):""":type strs: List[str]:rtype: str"""if not strs:return ""res = 0for i in range(len(strs[0])):flag = 0char = strs[0][i]for j in range(1, len(strs)):s = strs[j]if i >= len(s) or s[i] != char:flag = 1breakif flag == 1:breakelse:res += 1return strs[0][:res]

滑动窗口类问题

滑动窗口这类问题一般需要用到 双指针 来进行求解,一般都是基于字符串和数组的,题目问法大致有这几种:

  • 给两个字符串,一长一短,问其中短的是否在长的中满足一定的条件存在,例如:

    求长的的最短子串,该子串必须涵盖短的的所有字符

    短的的 anagram 在长的中出现的所有位置

  • 给一个字符串或者数组,问这个字符串的子串或者子数组是否满足一定的条件,例如:

    含有少于 k 个不同字符的最长子串

    所有字符都只出现一次的最长子串

除此之外,还有一些其他的问法,但是不变的是,这类题目脱离不开主串(主数组)和子串(子数组)的关系,要求的时间复杂度往往是 O(n) ,空间复杂度往往是常数级的。

思路是保证右指针每次往前移动一格,每次移动都会有新的一个元素进入窗口,这时条件可能就会发生改变,然后根据当前条件来决定左指针是否移动,以及移动多少格。

# 滑动窗口算法框架
def slidingWindow(s:str, p:str):# 输入参数有效性判断if ...:...# 申请一个散列,用于记录窗口中具体元素的个数情况dic = {}# 预处理(可省), 一般情况是改变 hash...# l 表示左指针, count 记录当前的条件,具体根据题目要求来定义,result 用来存放结果l, r = 0, 0count, res = 0, []while r < len(s):# 更新新元素在散列中的数量dic[s[r]] -= 1# 根据窗口的变更结果来改变条件值if dic[s[r]] == ... count += 1# 如果当前条件不满足,移动左指针直至条件满足为止while count > K or ...:...if ...:count -= 1dic[A[l]] += 1l += 1# 更新结果res = ...return res

这里面的 “移动左指针直至条件满足” 部分,需要具体题目具体分析,其他部分的变化不大。

找到字符串中所有字母异位词

给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。

字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。

说明:

字母异位词指字母相同,但排列不同的字符串。
不考虑答案输出的顺序。
示例 1:

输入:
s: “cbaebabacd” p: “abc”

输出:
[0, 6]

解释:
起始索引等于 0 的子串是 “cba”, 它是 “abc” 的字母异位词。
起始索引等于 6 的子串是 “bac”, 它是 “abc” 的字母异位词。

解法
首先窗口是固定的,窗口长度就是输入参数中第二个字符串的长度,也就是说,右指针移动到某个位置后,左指针必须跟着一同移动,且每次移动都是一格,模版中 count 用来记录窗口内满足条件的元素,直到 count 和窗口长度相等即可更新答案。

class Solution:def findAnagrams(self, s: str, p: str) -> List[int]:if len(s) < len(p):return []l, r = 0, 0count, res = 0, []dic = [0] * 26for i in range(len(p)):dic[ord(p[i]) - ord('a')] += 1while r < len(s):dic[ord(s[r]) - ord('a')] -= 1if dic[ord(s[r]) - ord('a')] >= 0:count += 1if r > len(p) - 1:dic[ord(s[l]) - ord('a')] += 1if dic[ord(s[l]) - ord('a')] > 0:count -= 1l += 1if count == len(p):res.append(l)r += 1return res

最小覆盖子串

给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。

示例:

输入:S = “ADOBECODEBANC”, T = “ABC”
输出:“BANC”

解法
同样是两个字符串之间的关系问题,因为题目求的最小子串,也就是窗口的最小长度,说明这里的窗口大小是可变的,这里移动左指针的条件变成,只要左指针指向不需要的字符,就进行移动。以及要设置一个Min_len随时更新最小长度。

class Solution:def minWindow(self, s: str, t: str) -> str:if len(s) < len(t):return ""l, r = 0, 0count, res, min_len = 0, "", len(s) + 1dic = {}for x in t:dic[x] = dic.get(x, 0) + 1while r < len(s):dic[s[r]] = dic.get(s[r], 0) - 1if dic[s[r]] >= 0:count += 1while l < r and dic[s[l]] < 0:dic[s[l]] += 1l += 1if count == len(t) and min_len > r - l + 1:min_len = r - l + 1res = s[l: r + 1]r += 1return res

找出包含序列的所有元素的最小长度子序列

给定一个序列如S = {1,8,2,1,4,1,2,9,1,8,4},我们需要找到包含S的所有元素的最小长度子序列(不重复,顺序不重要)。如何有效地找到这个子序列?注意:S:{1,2,4,8,9 }中有5个不同的元素,最小长度子序列必须包含所有这5个元素。

解法
类似于上面的题,只是简单了些,不考虑重复问题


def Test(s):dic = {}res, cnt, min_len = [], 0, len(s)l, r = 0, 0for x in s:dic[x] = 1while r < len(s):dic[s[r]] -= 1if dic[s[r]] == 0:cnt += 1while l < r and dic[s[l]] < 0:dic[s[l]] += 1l += 1if cnt == len(dic) and min_len > r - l + 1:min_len = r - l + 1res = s[l: r + 1]r += 1return ress = [1,8,2,1,4,1,2,9,1,8,4]
print(Test(s))

无重复字符的最长子串

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

示例 1:

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

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

解法
滑动窗口的方法,维护一个滑动窗口,窗口内的都是没有重复的字符,去尽可能的扩大窗口的大小,窗口不停的向右滑动。用一个字典存储每个字符的最后位置,随时判断窗口左端是否在当前字符最后位置的左边,如果是,那说明出现了重复,就更新。

class Solution(object):def lengthOfLongestSubstring(self, s):""":type s: str:rtype: int"""res = 0start = 0dic = {}for i in range(len(s)):if s[i] in dic and start <= dic[s[i]]:start = dic[s[i]] + 1dic[s[i]] = ires = max(res, i - start + 1)return res

K 个不同整数的子数组

给定一个正整数数组 A,如果 A 的某个子数组中不同整数的个数恰好为 K,则称 A 的这个连续、不一定独立的子数组为好子数组。

(例如,[1,2,3,1,2] 中有 3 个不同的整数:1,2,以及 3。)

返回 A 中好子数组的数目。

示例 1:

输入:A = [1,2,1,2,3], K = 2
输出:7
解释:恰好由 2 个不同整数组成的子数组:[1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2].

解法
滑动窗口两个指针,思路是给现有子数组右端添加一个元素后,要么当前数组依旧合法,要么我们需要在左端删除一些元素使它保持合法。tmp就是维护的当前窗口下合法的子数组个数,cnt是当前窗口的大小。

class Solution:def subarraysWithKDistinct(self, A: List[int], K: int) -> int:if not A or len(A) < K:return 0dic = {}res, cnt, tmp = 0, 0, 1l, r = 0, 0while r < len(A):dic[A[r]] = dic.get(A[r], 0) + 1if dic[A[r]] == 1:cnt += 1while dic[A[l]] > 1 or cnt > K:if cnt > K:tmp = 1cnt -= 1else:tmp += 1dic[A[l]] -= 1l += 1if cnt == K:res += tmpr += 1return res

替换后的最长重复字符

给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。

注意:
字符串长度 和 k 不会超过 104。

示例 1:

输入:
s = “ABAB”, k = 2

输出:
4

解释:
用两个’A’替换为两个’B’,反之亦然。

解法
问题在于怎么知道当前窗口中数量最多的字符的数量,因为需要替换的字符就是当前窗口的大小减去窗口中数量最多的字符的数量。
保存滑动窗口内相同字母出现次数的历史最大值,
通过判断窗口宽度(right - left + 1) - maxFreq > K来决定窗口是否做滑动,否则窗口就扩张
这里只需要记录历史最大值的原因是我们只需要最终保证输出的是最大长度,无需缩减窗口大小

class Solution:def characterReplacement(self, s: str, k: int) -> int:from collections import defaultdict# 动态滑动窗口maxLen, windowStart, maxFreq = 0, 0, 0# 统计出现频率freqDict = defaultdict(int)for windowEnd in range(len(s)):rightChar = s[windowEnd]freqDict[rightChar] += 1# 保存历史出现的最大频率maxFreq = max(freqDict[rightChar], maxFreq)# 缩小滑动窗口if (windowEnd - windowStart + 1 - maxFreq) > k:leftChar = s[windowStart]windowStart += 1freqDict[leftChar] -= 1       maxLen = max(maxLen, windowEnd - windowStart + 1)return maxLen

至多包含两个不同字符的最长子串

给定一个字符串 s ,找出 至多 包含两个不同字符的最长子串 t 。

示例 1:

输入: “eceba”
输出: 3
解释: t 是 “ece”,长度为3。

解法
双指针+滑动窗口,判断条件是当前窗口内不同元素数目最多两个。

class Solution:def lengthOfLongestSubstringTwoDistinct(self, s: str) -> int:from collections import defaultdictlookup = defaultdict(int)start = 0end = 0max_len = 0counter = 0while end < len(s):if lookup[s[end]] == 0:counter += 1lookup[s[end]] += 1end +=1while counter > 2:if lookup[s[start]] == 1:counter -= 1lookup[s[start]] -= 1start += 1max_len = max(max_len, end - start)return max_len

长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

进阶:
如果你已经完成了 O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。

解法
参考:https://blog.csdn.net/qq_17550379/article/details/80540430

  • 暴力破解,通过遍历所有的子数组找到满足条件的最小子数组:外面的循环是从第i个位置开始找以i开头的所有子数组,时间复杂度为O(N^2)
  • 二分搜索法:考虑是否存在mid长度子数组,我们将窗口的大小内元素值是否满足和>=s作为条件。时间复杂度就是O(nlogn)
  • 两个指针:通过累加两个指针的区间内的值和s比较,就可以在O(n)级别的时间内得到结果。定义指针 start 和 end 分别表示子数组的开始位置和阶数位置,维护变量 sum 存储子数组中的元素和。开始时 starts 和 end 都指向下标0,sum=0。每一轮迭代都将 nums[end] 加到 sum 中,如果 sum≥s ,更新子数组的最小常数,然后从 sum 中减掉 nums[start] ,并把 start 右移,直到 sum<s ,此过程中要更新子数组最小长度。每轮迭代后将 end 后移。

方法一:

class Solution(object):def minSubArrayLen(self, s, nums):""":type s: int:type nums: List[int]:rtype: int"""res = len(nums) + 1for i in range(len(nums)):cnt = 0for j in range(i, len(nums)):cnt += nums[j]if cnt >= s:res = min(res, j - i + 1)if res == len(nums) + 1:return 0return res

方法二:

class Solution:def getCnt(self, s, nums, k):cnt = 0for i in range(len(nums)):cnt += nums[i]if i >= k:cnt -= nums[i - k]if cnt >= s:return Truereturn Falsedef minSubArrayLen(self, s: int, nums: List[int]) -> int:l, r = 1, len(nums)res = 0while l <= r:mid = (l + r) // 2if self.getCnt(s, nums, mid):r = mid - 1res = midelse:l = mid + 1return res

方法三:

class Solution(object):def minSubArrayLen(self, s, nums):n = len(nums)start, end = 0,0mysum = 0ans = n+1while end < n:mysum += nums[end]while mysum >= s:ans = min(ans, end-start+1)mysum -= nums[start]start += 1end += 1return 0 if ans == n+1 else ans

字符串转换整数 (atoi)

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

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

如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。
假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。
该字符串在有效的整数部分之后也可能会存在多余的字符,那么这些字符可以被忽略,它们对函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换,即无法进行有效转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0 。

提示:

本题中的空白字符只包括空格字符 ’ ’ 。
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。

示例 1:

输入: “42”
输出: 42
示例 2:

输入: " -42"
输出: -42
解释: 第一个非空白字符为 ‘-’, 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:

输入: “4193 with words”
输出: 4193
解释: 转换截止于数字 ‘3’ ,因为它的下一个字符不为数字。
示例 4:

输入: “words and 987”
输出: 0
解释: 第一个非空字符是 ‘w’, 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:

输入: “-91283472332”
输出: -2147483648
解释: 数字 “-91283472332” 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。

解法

  • 正则表达式:^:匹配字符串开头;[+-]:代表一个+字符或-字符;?:前面一个字符可有可无;\d:一个数字;+:前面一个字符的一个或多个;\D:一个非数字字符;*:前面一个字符的0个或多个;max(min(数字, 2∗∗31−12**31 - 12∗∗31−1), −2∗∗31-2**31−2∗∗31) 用来防止结果越界

  • 状态转移自动机:我们的程序在每个时刻有一个状态 s,每次从序列中输入一个字符 c,并根据字符 c 转移到下一个状态 s’。这样,我们只需要建立一个覆盖所有情况的从 s 与 c 映射到 s’ 的表格即可解决题目中的问题。时间复杂度:O(n),空间复杂度:O(1)

方法一:

class Solution:def myAtoi(self, s: str) -> int:return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31)

方法二:

INT_MAX = 2 ** 31 - 1
INT_MIN = -2 ** 31class Automaton:def __init__(self):self.state = 'start'self.sign = 1self.ans = 0self.table = {'start': ['start', 'signed', 'in_number', 'end'],'signed': ['end', 'end', 'in_number', 'end'],'in_number': ['end', 'end', 'in_number', 'end'],'end': ['end', 'end', 'end', 'end'],}def get_col(self, c):if c.isspace():return 0if c == '+' or c == '-':return 1if c.isdigit():return 2return 3def get(self, c):self.state = self.table[self.state][self.get_col(c)]if self.state == 'in_number':self.ans = self.ans * 10 + int(c)self.ans = min(self.ans, INT_MAX) if self.sign == 1 else min(self.ans, -INT_MIN)elif self.state == 'signed':self.sign = 1 if c == '+' else -1class Solution:def myAtoi(self, str: str) -> int:automaton = Automaton()for c in str:automaton.get(c)return automaton.sign * automaton.ans

将汉字数字转换成阿拉伯数字

解法
Python把用汉字表示的数字转换为阿拉伯数字前,需要先用到字典形式,分别存储下字和单位与数字的分别的对应关系。开始处理简单情况,判断是数字还是单位,如果是单位就用一个tmp值存下大小,如果是数字就乘以刚才的单位。对于超过一万的数字可以单独处理一下,以及对10-19的数字也需要在循环后单独处理。

CN_NUM = { u'〇': 0, u'一': 1, u'二': 2, u'三': 3, u'四': 4, u'五': 5, u'六': 6, u'七': 7, u'八': 8, u'九': 9,u'零': 0, u'壹': 1, u'贰': 2, u'叁': 3, u'肆': 4, u'伍': 5, u'陆': 6, u'柒': 7, u'捌': 8, u'玖': 9,u'貮': 2, u'两': 2,}
CN_UNIT = { u'十': 10, u'拾': 10, u'百': 100, u'佰': 100, u'千': 1000, u'仟': 1000,  u'万': 10000, u'萬': 10000, u'亿': 100000000, u'億': 100000000, u'兆': 1000000000000,}def cn2dig(cn):lcn = list(cn)unit = 0  # 当前的单位ldig = []  # 临时数组while lcn:cndig = lcn.pop()if CN_UNIT.has_key(cndig):unit = CN_UNIT.get(cndig)if unit == 10000:ldig.append('w')  # 标示万位unit = 1elif unit == 100000000:ldig.append('y')  # 标示亿位unit = 1elif unit == 1000000000000:  # 标示兆位ldig.append('z')unit = 1continueelse:dig = CN_NUM.get(cndig)if unit:dig = dig * unitunit = 0ldig.append(dig)if unit == 10:  # 处理10-19的数字ldig.append(10)ret = 0tmp = 0while ldig:x = ldig.pop()if x == 'w':tmp *= 10000ret += tmptmp = 0elif x == 'y':tmp *= 100000000ret += tmptmp = 0elif x == 'z':tmp *= 1000000000000ret += tmptmp = 0else:tmp += xret += tmpreturn ret# ldig.reverse()# print ldig# print CN_NUM[u'七']if __name__ == '__main__':test_dig = [u'九',u'十一',u'一百二十三',u'一千二百零三',u'一万一千一百零一',u'十万零三千六百零九',u'一百二十三万四千五百六十七',u'一千一百二十三万四千五百六十七',u'一亿一千一百二十三万四千五百六十七',u'一百零二亿五千零一万零一千零三十八',u'一千一百一十一亿一千一百二十三万四千五百六十七',u'一兆一千一百一十一亿一千一百二十三万四千五百六十七',]for cn in test_dig:printcn2dig(cn)

字符串--Leetcode (python)相关推荐

  1. LEETCODE | PYTHON | 剑指 Offer 58 - Ⅱ | 左旋转字符串

    LEETCODE | PYTHON | 剑指 Offer 58 - Ⅱ | 左旋转字符串 1. 题目 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部.请定义一个函数实现字符串左旋转操作 ...

  2. 逗号分隔的字符串转换为Python中的列表 split

    将逗号分隔的字符串转换为Python中的列表 给定一个字符串: 它是由逗号分隔的几个值的序列: mStr = '192.168.1.1,192.168.1.2,192.168.1.3' 如何将字符串转 ...

  3. python中什么是字符举例说明_第20p,什么是字符串?Python中的str

    原标题:第20p,什么是字符串?Python中的str 大家好,我是杨数Tos,这是<从零基础到大神>系列课程的第20篇文章,第二阶段的课程:Python基础知识:Python的字符串(上 ...

  4. Leetcode python《热题 HOT 100》15. 三数之和

    Leetcode python 之 <热题 HOT 100>:https://leetcode-cn.com/problemset/hot-100/ 15. 三数之和 给定一个包含 n 个 ...

  5. Leetcode python《热题 HOT 100》1. 两数之和

    Leetcode python 之 <热题 HOT 100>:https://leetcode-cn.com/problemset/hot-100/ 1. 两数之和 给定一个整数数组 nu ...

  6. 13-19 Python Number、Python字符串、Python列表(List)、集合的基本操作、元组、字典Dicttionnary、日期和时间

    13 Python Number Python Number数据类型用于存储数值. 数据类型是不允许改变的,这就是意味着如果改变Number数据类型的值,将重新分配内存空间. 以下实例在变量赋值时Nu ...

  7. python列表元组字符串都属于有序数列_列表、元组、字符串是Python的__________(有序、无序?)序列。...

    [简答题]朗读d教科书第35页"貿易レターコラム 消費価格値上げ再考のお願い"的李文,直接读标题,然后读"拝啓"和全文.注意作业提交截止日期. [多选题]以下语 ...

  8. python列表添加字符串_2.python基础之—列表,元组,字典,集合,字符串的使用方法...

    一.关于python序列的简介. python里面的序列大部分都可以执行,索引,切片,加,乘,检查长度,以及检查某个成员是否存在,甚至还可以找出这个序列中最小的元素和最大的元素,并且序列都是可迭代的. ...

  9. python 字符串 变量_检查变量是否为字符串的Python程序

    python 字符串 变量 Python | 检查变量是否为字符串 (Python | Check if a variable is a string) To check whether a defi ...

最新文章

  1. 调试寄存器(debug registers, DRx)理论及实践
  2. PyTorch基础-模型的保存和加载-09
  3. 线程Blocked--SynchronizedDemo
  4. java程序员饱和了吗?
  5. c# 修饰词public, protected, private,internal的区别
  6. Dumpsys Input Diagnostics
  7. elsevier模板_英文论文双栏模板
  8. [转]2020 年最具潜力 44 个顶级开源项目,涵盖 11 类 AI 学习框架、平台(值得收藏)
  9. antv图表 根据屏幕大小响应式_做可交互的统计图表,这套图形语法不容错过
  10. delphi 如何知道 Treeview,Listview 当前最上面显示的节点
  11. onmouseover|onmouseout和onmouseenter|onmouseleave的区别
  12. 卷积神经网络 第三周作业:Residual+Networks+-+v1
  13. ISA Server 2006速战速决实验指南(7) 创建元素-网络对象
  14. 关于PV,流量和带宽
  15. android 版本号命名规范,软件版本号命名规则
  16. <EDEM MBD案例02>EDEM-Adams
  17. vue元素实现动画过渡效果
  18. 计算机专业需要学习打字吗,电脑学习打字的最快方法是什么
  19. 新生儿喝奶后不要马上放回床上睡觉,为宝宝健康着想,先做1件事
  20. Parsec 移动宽带无法登录问题和设置代理方法

热门文章

  1. 并行编程,绝不是你想的那么简单
  2. 思考(七十四):一个游戏后端分布式事务架构介绍
  3. 设置图表标题、坐标轴标题及窗口标题
  4. python3基础系列之六【输入输出file方法】
  5. 关于函数中的return
  6. 川土微数字隔离器CA-IS36XX高性能数字隔离器 可替代TI ADI MAX等
  7. 背负着24-70之名 佳能新老镜皇横向对比(MTF对比说明)
  8. R语言读取文件报错之二:Error in read.table(“xxxx.txt“, header = TRUE) : 列的数目比列的名字要多
  9. 给小伙伴们的json数据
  10. 更改sendmail附件大小限制