给定一个字符串数组,再给定整数 k ,请返回出现次数前k名的字符串和对应的次数。
返回的答案应该按字符串出现频率由高到低排序。如果不同的字符串有相同出现频率,按字典序排序。
对于两个字符串,大小关系取决于两个字符串从左到右第一个不同字符的 ASCII 值的大小关系。
比如"ah1x"小于"ahb","231"<”32“
字符仅包含数字和字母
数据范围:字符串数满足
,每个字符串长度
,
要求:空间复杂度
,时间复杂度
["a","b","c","b"],2
[["b","2"],["a","1"]]
"b"出现了2次,记["b","2"],"a"与"c"各出现1次,但是a字典序在c前面,记["a","1"],最后返回[["b","2"],["a","1"]]
["123","123","231","32"],2
[["123","2"],["231","1"]]
"123"出现了2次,记["123","2"],"231"与"32"各出现1次,但是"231"字典序在"32"前面,记["231","1"],最后返回[["123","2"],["231","1"]]
["abcd","abcd","abcd","pwb2","abcd","pwb2","p12"],3
[["abcd","4"],["pwb2","2"],["p12","1"]]
#
# return topK string
# @param strings string字符串一维数组 strings
# @param k int整型 the k
# @return string字符串二维数组
#
class Solution:
def topKstrings(self , strings , k ):
if not strings:
return None
# 用字典统计每个单词的数量
mydict = {}
for word in strings:
if word in mydict:
mydict[word] += 1
else:
mydict[word] = 1
# 按value域降序排列,返回值是list
cur = sorted(mydict.items(), key=lambda x: x[1], reverse=True)
mylist = []
for item in cur:
tar = []
tar.append(item[0])
tar.append(str(item[1]))
mylist.append(tar)
# 设置临时容器,存放相同value值的单词
temp = [mylist[0]]
i, j = 0, 1
ans = []
while j < len(mylist):
# 若两个单词的频数相等
if mylist[j][1] == mylist[i][1]:
# value值相同则将单词放入temp中,准备字母排序
temp.append(mylist[j])
# 指针后移
i += 1
j += 1
else:
# 将相同value值的按字母排序,加到ans中
temp.sort()
ans += temp
# temp清空,准备记录下一轮
temp = []
# 指针后移
i += 1
j += 1
# 开始记录新的一轮
temp.append(mylist[i])
# 最后一轮的temp还没有处理,别落下
temp.sort()
ans += temp
return ans[:k] class Solution:
def topKstrings(self, strings, k ):
# write code here
# 哈希统计次数
count = {}
for char in strings:
count[char] = count.get(char, 0) + 1
# 定义排序函数 (按次数降序,字典序升序)
result = sorted(count.items(), key = lambda x: (-x[1],x[0]))
# 排序完的前k个
return result[:k] class Solution:
def topKstrings(self , strings , k):
res = {}
result = []
max_count = 0
for i in strings:
res[i] = res.get(i, 0) + 1
max_count = max(max_count, res[i])
ans = [[] for _ in range(max_count + 1)]
for key, value in res.items():
ans[value].append(key)
for j in range(max_count + 1):
if ans[max_count - j] != []:
ans[max_count - j] = sorted(ans[max_count - j])
if len(ans[max_count - j]) < k:
for ele in ans[max_count - j]:
result += [[ele, str(max_count - j)]]
k -= len(ans[max_count - j])
else:
for ele in range(k):
result += [[ans[max_count - j][ele], str(max_count - j)]]
return result #
# return topK string
# @param strings string字符串一维数组 strings
# @param k int整型 the k
# @return string字符串二维数组
#
class Solution:
def topKstrings(self , strings , k ):
# write code here
def topk(li, k):
heap = li[0:k] # 取列表前k个元素
for i in range((k - 2) // 2, -1, -1): # 前k个元素构建堆
sift(heap, i, k - 1)
for i in range(k, len(li)): # 从列表第k + 1个元素(index为k)继续遍历
if li[i] < heap[0]: # 如果遍历的当前元素小于堆顶,则替换堆顶并进行一次调整
heap[0] = li[i]
sift(heap, 0, k - 1)
for i in range(k - 1, 0, -1): # 挨个出数
heap[0], heap[i] = heap[i], heap[0]
sift(heap, 0, i - 1)
return heap # 返回排好序的前k个数
def sift(li, high, low):
"""
调整函数(大根堆)
此时的列表li除根结点(low)外,其它部分已经无需调整了
大根堆:上层大下层小
:param li: 列表
:param low: 堆的根结点位置(堆顶)
:param high: 堆的最后一个元素位置,唯一作用为不让j越界,间接使得i不越界
:return:
"""
i = low # i指向父亲(初始化时指向堆顶)
j = 2 * i + 1 # j指向孩子,默认首先指向左孩子
tmp = li[low] # 存放堆顶
while j <= high: # 只要j没有超过堆的最后一个元素位置,继续循环
if j + 1 <= high and li[j] < li[j + 1]: # 如果右孩子存在且右孩子比左孩子更大
j += 1 # j指向右孩子
if li[j] > tmp: # 孩子比tmp大
li[i] = li[j] # 孩子放到父亲的位置
i = j # i向下移一层(指向原来孩子的位置)
j = 2 * i + 1 # 同时j也向下移一层
else: # tmp比孩子大
# li[i] = tmp # tmp放到父亲的位置
break
# else: # j超过堆的最后一个元素位置
# li[i] = tmp # 直接将tmp放到堆的最下一层
li[i] = tmp # 观察上面两个else,发现while循环结束时始终会执行一次li[i] = tmp,因此可简化
li = list(map(int, strings))
print(li)
res = list()
res = topk(li, k)
dic = {}
for i in res:
dic[i] = dic.get(i, 0) + 1
fin = list()
for i in dic:
fin.append([i, str(dic[i])])
fin.sort()
return fin