字符串
一、基于字符计数的问题
1.偶数子串的数量
给定一串0到9的数字。任务是计算在将整数转换为偶数时的子串的数量。
Input : str = "1234".
Output : 6
“2”, “4”, “12”, “34”, “234”, “1234是6个子字符串,它们是偶数。
def evenNum(s): count = 0 for i in range(len(s)): if int(s[i]) % 2 == 0: count += i + 1 return count
2.学生出勤记录
给你一个代表学生出勤记录的字符串。 该记录只包含以下三个字符:
'A' : 缺席.
'L' : 迟到.
'P' : 出席.
如果学生的出勤记录不包含多于一个“A”(缺席)或超过两个连续的“L”(迟
到),则可以获得奖励。
你需要根据他的出勤记录来返回学生是否可以得到奖励。
def checkRecord(self, s): return not (s.count('A') > 1 or 'LLL' in s)
3.对具有相同首尾字符的子字符进行计数
给出一个字符串S,我们需要找到所有连续的子字符串开始和结束的字符都相同的
计数。
Input : S = "abcab"
Output : 7
"abcab" 有15个子字符串
在上面的子串中,有7个子串满足要求:a,abca,b,bcab,c,a和b。.
方法一:暴力
def countSub(s): result = 0 for i in range(len(s)): for j in range(i, len(s)): if (s[i] == s[j]): result += 1 return result
方法二:
from collections import Counter def countSub(s): counter = Counter(s) result = 0 for x in counter: result += counter[x] * (counter[x] + 1) // 2 return result
4.计数问题 IV
字符串中最大连续重复字符
给定一个字符串,其任务是在字符串中查找最大连续重复字符。
def maxRepeating(s): n = len(s) count = 0 result = s[0] local = 1 for i in range(n): if (i < n - 1 and s[i] == s[i+1]): local += 1 else: if (local > count): count = local result = s[i] local = 1 return result
5.排序数组中删除重复
def removeDuplicates(A): if not A: return 0 newTail = 0 for i in range(1, len(A)): if A[i] != A[newTail]: newTail += 1 A[newTail] = A[i] for j in range(newTail + 1, len(A)): A[j] = 'X' print(A) return newTail + 1
二、同字母异序
1.同字母异序词
编写一个函数来检查两个给定的字符串是否彼此是相同字母异序词。 一个字符串的相同字
母异序词是另一个包含相同字符的字符串,只有字符的顺序可以不同。 例如,“abcd”和
“dabc”是彼此的相同字母异序词。
方法一:排序
def areAnagram(str1, str2): if len(str1) != len(str2): return False return sorted(str1) == sorted(str2)
方法二:
from collections import Counter def areAnagram(str1, str2): return Counter(str1) == Counter(str2)
2.同字母异序词 II
查找字符串中的所有相同字母异序词
给定字符串s和非空字符串p,在s中找到所有p的相同字母异序词的起始索引。
字符串只包含小写英文字母,字符串s和p的长度不会超过20,100。
输出的顺序并不重要。
Input:
s: "cbaebabacd" p: "abc"
Output: [0, 6]
解释:
以0作为起始索引 的子序列是 “cba”,它是"abc"的相同字母异序词.
以6作为起始索引 的子序列是 “bac”,它是"abc"的相同字母异序词.
from collections import Counter def findAnagrams(s, p): res = [] pCounter = Counter(p) sCounter = Counter(s[:len(p) - 1]) for i in range(len(p) - 1,len(s)): sCounter[s[i]] += 1 # include a new char in the window if sCounter == pCounter: # This step is O(1), since there are at most 26 English letters res.append(i-len(p)+1) # append the starting index sCounter[s[i-len(p)+1]] -= 1 # decrease the count of oldest char in the window if sCounter[s[i-len(p)+1]] == 0: del sCounter[s[i-len(p)+1]] # remove the count if it is 0 return res
3.查找同字母异序词的映射
给定两个列表A和B,B是A的一个同字母组。这意味着B是通过随机化A中元素的顺
序而创建的。
我们希望找到一个从A到B的索引映射P。映射P [i] = j意味着列表A中的第i个元
素出现在B的索引为j的位置。
这些列表A和B可能包含重复项。 如果有多个答案,则输出它们中的任意一个。
例如,给定
A = [12, 28, 46, 32, 50]
B = [50, 12, 32, 46, 28]
应当返回[1, 4, 3, 2, 0]
P[0] = 1因为A的第0个元素出现在B[1]处,并且P[1] = 4,因为A的第1个元素出
现在B [4]处,依此类推。
方法一:O(N2)
def anagramMappings1(A, B): answer = [] for a in A: for i,b in enumerate(B): if a == b: answer.append(i) break return answer
另:
def anagramMappings2(A, B): return [B.index(a) for a in A]
方法二:O(N)
def anagramMappings3(A, B): d = {} for i,b in enumerate(B): d[b] = i return [d[a] for a in A]
三、回文
1.移位
给定两个字符串s1和s2,写一段程序说明s2是否是s1 的移位。
def areRotations(string1, string2): size1 = len(string1) size2 = len(string2) if size1 != size2: return 0 temp = string1 + string1 return temp.count(string2) > 0
2.移位 II
写一个函数 rotate(arr[], d, n) 将大小为n的数组arr[] 移位d个单位。
def reverse(arr, start, end): while start < end: arr[start], arr[end] = arr[end], arr[start] start += 1 end -= 1 def rotate(arr, d): n = len(arr) reverse(arr, 0, d - 1) reverse(arr, d, n - 1) reverse(arr, 0, n - 1)
3.回文数
判断一个整数是否是回文数。当一个整数从前从后读一样时可判定为回文数。
def isPalindrome(s): return s == s[::-1]
def isPalindrome(s): for i in range(len(s) // 2): if s[i] != s[- 1 - i]: return False return True
判断整数:
def isPalindrome(x): if x < 0: return False ranger = 1 while x // ranger >= 10: ranger *= 10 print(ranger) while x: left = x // ranger right = x % 10 if left != right: return False x = (x % ranger) // 10 ranger //= 100 return True
4.移位回文
检查给定的字符串是否是一个回文字符串的移位。
def isRotationOfPalindrome(s): # If string itself is palindrome if isPalindrome(s): return True # Now try all rotations one by one n = len(s) for i in range(len(s) - 1): s1 = s[i+1:n] s2 = s[0:i+1] # Check if this rotation is palindrome s1 += s2 if isPalindrome(s1): return True return False
另:
def isRotationOfPalindrome(s): n = len(s) s = s + s for i in range(n): if isPalindrome(s[i : i + n]): return True return False
5.重排回文
给定一个字符串,检查字符串中的各字符是否可以构成一个回文字符串。
from collections import Counter def canRearrage(s): odd = 0 counter = Counter(s) for key in counter.keys(): if counter[key] % 2 == 1: odd += 1 if odd > 1: return False return True
6.最长回文
给定一个由大小写字母组成的字符串,找到可由这些字符构成的最长的回文字符串。
本例是大小写敏感的,例如“Aa”在此处不被认为是回文字符串。
from collections import Counter def longestPalindrome(s): ans = 0 counter = Counter(s) for key in counter.keys(): v = counter[key] ans += v // 2 * 2 if ans % 2 == 0 and v % 2 == 1: ans += 1 return ans
7.回文流判定
# d is the number of characters in input alphabet d = 256 # q is a prime number used for evaluating Rabin Karp's # Rolling hash q = 103 def checkPalindromes(string): # Length of input string N = len(string) # A single character is always a palindrome print(string[0] + " Yes") # Return if string has only one character if N == 1: return # Initialize first half reverse and second half for # as firstr and second characters firstr = ord(string[0]) % q second = ord(string[1]) % q h = 1 i = 0 j = 0 # Now check for palindromes from second character # onward for i in range(1,N): # If the hash values of 'firstr' and 'second' # match, then only check individual characters if firstr == second: # Check if str[0..i] is palindrome using # simple character by character match for j in range(0,i//2): if string[j] != string[i-j]: break j += 1 if j == i//2: print(string[i] + " Yes") else: print(string[i] + " No") else: print(string[i] + " No") # Calculate hash values for next iteration. # Don't calculate hash for next characters if # this is the last character of string if i != N-1: # If i is even (next i is odd) if i % 2 == 0: # Add next character after first half at # beginning of 'firstr' h = (h*d) % q firstr = (firstr + h*ord(string[i//2]))%q # Add next character after second half at # the end of second half. second = (second*d + ord(string[i+1]))%q else: # If next i is odd (next i is even) then we # need not to change firstr, we need to remove # first character of second and append a # character to it. second = (d*(second + q - ord(string[(i+1)//2])*h)%q + ord(string[i+1]))%q