题目:
定义一个函数 f(s),统计 s 中(按字典序比较)最小字母的出现频次 ,其中 s 是一个非空字符串。
例如,若 s = “dcce”,那么 f(s) = 2,因为字典序最小字母是 “c”,它出现了 2 次。
现在,给你两个字符串数组待查表 queries 和词汇表 words 。对于每次查询 queries[i] ,需统计 words 中满足 f(queries[i]) < f(W) 的 词的数目 ,W 表示词汇表 words 中的每个词。
请你返回一个整数数组 answer 作为答案,其中每个 answer[i] 是第 i 次查询的结果。
示例 1:
输入:queries = [“cbd”], words = [“zaaaz”]
输出:[1]
解释:查询 f(“cbd”) = 1,而 f(“zaaaz”) = 3 所以 f(“cbd”) < f(“zaaaz”)。
示例 2:
输入:queries = [“bbb”,“cc”], words = [“a”,“aa”,“aaa”,“aaaa”]
输出:[1,2]
解释:第一个查询 f(“bbb”) < f(“aaaa”),第二个查询 f(“aaa”) 和 f(“aaaa”) 都 > f(“cc”)。
提示:
1 <= queries.length <= 2000
1 <= words.length <= 2000
1 <= queries[i].length, words[i].length <= 10
queries[i][j]、words[i][j] 都由小写英文字母组成
思路:
- 根据定义 f(s)=s.count(min(s)) 就可以快速计算最小字母出现的频次
- 将字母抽象为数字问题,将queries和words中的最小字母出现频次储存到q和w列表中
- 将w排序
- 遍历q中元素,二分法来选择比q中元素大的个数
语法知识:
min()函数可以计算字符串中的最小元素
len(w)-l是返回比目标元素大的个数
法:
bisect_right 的返回值表示在保持排序的情况下,插入 x 后它应该在哪个位置。这意味着,如果返回值为 i,那么 x 应该插入到 a[i] 之前。
注意:
bisect_right 会在列表中查找第一个大于等于 x 的元素,如果 x 已经存在于列表中,则返回值为 x 在列表中的下标加 1。
如果 x 比列表中所有元素都大,则返回值为列表的长度。
示例:
a = [1, 3, 5, 7, 9]
bisect_right(a, 4)
2
bisect_right(a, 10)
5
bisect_right(a, 3)
2
代码:
我的代码:
class Solution(object):
def numSmallerByFrequency(self, queries, words):
q = []
w = []
answer = []
for s in words:
w.append(s.count(min(s)))
for n in queries:
q.append(n.count(min(n)))
w.sort()
for i in q:
l = 0
r = len(w) - 1
while l <= r:
mid = (l + r) // 2
if w[mid] <= i:
l = mid + 1 # 赋值给 l
else:
r = mid - 1
answer.append(len(w) - l) # 添加到 answer 列表中
return answer
灵神的代码简洁优雅:
class Solution:
def numSmallerByFrequency(self, queries: List[str], words: List[str]) -> List[int]:
a = sorted(s.count(min(s)) for s in words)
return [len(a) - bisect_right(a, q.count(min(q))) for q in queries]
一些解释:
-
计算 words 中每个字符串的最小字母出现频次: a = sorted(s.count(min(s)) for s in words)
for s in words: 循环遍历 words 列表中的每个字符串 s。
min(s): 获取字符串 s 中的最小字母。
s.count(min(s)): 计算最小字母在字符串 s 中出现的次数。
sorted(…): 对所有字符串的最小字母出现频次进行排序,并存储到列表 a 中。 -
循环遍历查询字符串:
return [len(a) - bisect_right(a, q.count(min(q))) for q in queries]
for q in queries:
循环遍历 queries 列表中的每个查询字符串 q。
q.count(min(q)):
计算查询字符串 q 中最小字母的出现频次。 bisect_right(a, q.count(min(q))):
使用bisect_right 函数在排序后的列表 a 中找到第一个大于等于 q.count(min(q)) 的元素的下标,即 a 中所有小于
q.count(min(q)) 的元素数量。
len(a) - bisect_right(…):
计算 a 中所有大于q.count(min(q)) 的元素数量,即 words 中最小字母出现频次大于 q 中最小字母出现频次的字符串数量。 […]:
将每个查询字符串的比较结果存储到列表中,并返
回。