给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。
代码:
待改进,有重复元素会出错
# 方法一 直接排序
nums = [3, 1, 6, 4, 6, 1, 2]
k = 2
nums.sort()
print(nums)
print(len(nums) - k)
# 方法二 快速排序
import random
class Solution:
def findKthLargest(self, nums, k):
def Qsort(left, right):
if left >= right:
return -1
randindex = random.randint(left, right - 1)
nums[left], nums[randindex] = nums[randindex], nums[left]
l , r, pivot = left, right, nums[left]
while l < r:
while nums[r] >= pivot and l < r:
r -= 1
nums[l] = nums[r]
while nums[l] <= pivot and l < r:
l += 1
nums[r] = nums[l]
nums[r] = pivot
Qsort(left, l - 1)
Qsort(l + 1, right)
Qsort(0, len(nums) - 1)
return nums[len(nums) - k]
# 方法三 堆排序 (重复会报错)
def findKthLargest_heapsort(self):
def heapsort(nums, i, right):
left = 2 * i + 1
# 堆调整
while left <= right:
# 左节点是最后一个节点
if left == right:
if nums[left] > nums[i]:
nums[left], nums[i] = nums[i], nums[left]
else:
break
if nums[left] < nums[left + 1]:
left += 1
if nums[i] < nums[left]:
nums[left], nums[i] = nums[i], nums[left]
i = left
left = 2 * i + 1
else:
break
# 创建大顶堆,从最后一个有子节点的非叶子节点开始,往前遍历
for i in range((len(nums) - 1) // 2, -1, -1):
heapsort(nums, i, len(nums) - 1)
print(nums)
for right in range(len(nums) - 1, -1, -1):
nums[0], nums[right] = nums[right], nums[0]
self.k -= 1
if self.k == 0:
print(nums[right])
return nums[right]
heapsort(nums, 0, right - 1)
print(nums)
示例代码:
class Solution(object):
def findKthLargest(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
max_n = max(nums)
min_n = min(nums[:k])
l = [0] * (max_n - min_n + 1)
for n in nums:
if n < min_n:
continue
l[n - min_n] += 1
c = 0
for i in range(max_n - min_n, -1, -1):
c += l[i]
if c >= k:
return i + min_n
return min_n
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按任意顺序返回答案。
代码:
(很爱偷懒的一些女的
# 方法一 counter()
import collections
class Solution(object):
def topKFrequent(self, nums, k):
return list(zip(*collections.Counter(nums).most_common(k)))[0]
# 方法二 桶排序
class Solution(object):
def topKFrequent(self, nums, k):
counter = collections.Counter(nums)
n = len(nums)
dic = [ [] for i in range(n + 1)]
for v, c in counter.items():
dic[c].append(v)
res = []
for i in range(n, -1, -1):
res.extend(dic[i])
if len(res) == k:
return res
# 方法三 堆排序
def topK_heapsort(self):
freq = collections.Counter(nums)
dic, ans = [], []
for i in freq:
heapq.heappush(dic, (-freq[i], i))
for _ in range(k):
ans.append(heapq.heappop(dic)[1])
print('the top k frequent elems are', ans)
return ans
# 方法四 随机快排
def topKfreq_Qsort(self):
def topKfrequence(nums, k):
freq = collections.Counter(nums)
value = list(freq.keys())
l , r = 0 , len(value) - 1
while l <= r:
pivot = Qsort(value, l , r, freq)
if pivot == k - 1:
return value[:k]
elif pivot > k - 1:
r = pivot - 1
else:
l = pivot + 1
def Qsort(value,l, r, freq):
randindex = random.randint(l, r)
nums[l], nums[randindex] = nums[randindex], nums[l]
right, pivot = l, r
for i in range(l , r):
if freq.get(value[i]) >= freq.get(value[pivot]):
value[i], value[right] = value[right], value[i]
right += 1
value[right], value[pivot] = value[pivot], value[i]
return right
print(topKfrequence(nums, k))
给定一个字符串 s ,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。返回已排序的字符串 。如果有多个答案,返回其中任何一个。
import collections
class Solution(object):
def frequencySort(self, s):
freq = collections.Counter(s)
dic = []
for key, value in freq.items():
dic.append((key, value))
dic.sort(key = lambda x:x[1], reverse = True)
ans = []
for i in dic:
if i[1] > 1:
ans.append(i[0]*i[1])
else:
ans.append(i[0])
return ''.join(ans)
@TODO 桶排序
@TODO 堆排序
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。必须在不使用库内置的 sort 函数的情况下解决这个问题。
代码:
# 双指针
import random
class Solution(object):
def sortColors(self, nums):
l , r = 0 , len(nums) - 1
i = 0
while i <= r:
while nums[i] == 2 and i <= r:
nums[i], nums[r] = nums[r], nums[i]
r -= 1
if nums[i] == 0:
nums[i], nums[l] = nums[l], nums[i]
l += 1
i += 1
1.欧几里得算法(辗转相除法):
a,b为正整数,求a和b的最大公因数可以转化为求b和a%b的最大公因数
证明过程详见:https://blog.csdn.net/alicek1008/article/details/119559494
2.前k个高频元素多种解法:
https://blog.csdn.net/AI414010/article/details/108704282
3.堆排序:
https://zhuanlan.zhihu.com/p/124885051
4.根据字符出现频率排序多种解法
https://blog.csdn.net/weixin_45069761/article/details/106136422
import collections
import heapq
from pyparsing import nums
import random
class sort_algrms(object):
def __init__(self, nums, k, s, color):
self.nums = nums
self.k = k
self.s = s
self.color = color
# 选择排序 o(n^2)
def selected_sort(self):
def findSmallestWord(nums):
smallest = nums[0]
smallest_index = 0
for i in range(1, len(nums)):
if nums[i] < smallest:
smallest = nums[i]
smallest_index = i
return smallest_index
newnums = []
for j in range(len(nums)):
smallest_word = findSmallestWord(nums)
# pop() 内含一个要删除元素的索引
newnums.append(nums.pop(smallest_word))
nums[:] = newnums
print('the newnums is', nums)
return nums
# 1.找第k个最大的元素
# 方法一随机快排
def findKthLargest(self):
def Qsort(left, right):
if left >= right:
return -1
randindex = random.randint(left, right - 1)
nums[left], nums[randindex] = nums[randindex], nums[left]
l, r, pivot = left, right, nums[left]
while l < r:
while nums[r] >= pivot and l < r:
r -= 1
nums[l] = nums[r]
while nums[l] <= pivot and l < r:
l += 1
nums[r] = nums[l]
nums[r] = pivot
Qsort(left, l - 1)
Qsort(l + 1, right)
Qsort(0, len(nums) - 1)
print('the sorted num is', nums)
print(nums[len(nums)-k])
return nums[len(nums)-k]
# 方法二 堆排序 (重复会报错)
def findKthLargest_heapsort(self):
def heapsort(nums, i, right):
left = 2 * i + 1
# 堆调整
while left <= right:
# 左节点是最后一个节点
if left == right:
if nums[left] > nums[i]:
nums[left], nums[i] = nums[i], nums[left]
else:
break
if nums[left] < nums[left + 1]:
left += 1
if nums[i] < nums[left]:
nums[left], nums[i] = nums[i], nums[left]
i = left
left = 2 * i + 1
else:
break
# 创建大顶堆,从最后一个有子节点的非叶子节点开始,往前遍历
for i in range((len(nums) - 1) // 2, -1, -1):
heapsort(nums, i, len(nums) - 1)
print(nums)
for right in range(len(nums) - 1, -1, -1):
nums[0], nums[right] = nums[right], nums[0]
self.k -= 1
if self.k == 0:
print(nums[right])
return nums[right]
heapsort(nums, 0, right - 1)
print(nums)
# 2.出现频率最高的前k个元素
# 方法一 :桶排序
def topKFrequent(self):
counter = collections.Counter(nums)
n = len(nums)
# 与数组长度一样多个空列表(桶),只取了排好顺序的元素,没有取频次
dic = [ [] for i in range(n + 1)]
for v, c in counter.items():
dic[c].append(v)
# print(dic)
res = []
for i in range(n, -1, -1):
res.extend(dic[i])
# 倒取前k个桶
if len(res) == k:
print('the top k frequent elems are', res)
return res
# 方法二 counter()
def topKFrequent_counter(self):
return list(zip(*collections.Counter(nums).most_common(k)))[0]
# 方法三 堆排序
def topK_heapsort(self):
freq = collections.Counter(nums)
dic, ans = [], []
for i in freq:
heapq.heappush(dic, (-freq[i], i))
for _ in range(k):
ans.append(heapq.heappop(dic)[1])
print('the top k frequent elems are', ans)
return ans
# 方法四 随机快排
def topKfreq_Qsort(self):
def topKfrequence(nums, k):
freq = collections.Counter(nums)
value = list(freq.keys())
l , r = 0 , len(value) - 1
while l <= r:
pivot = Qsort(value, l , r, freq)
if pivot == k - 1:
return value[:k]
elif pivot > k - 1:
r = pivot - 1
else:
l = pivot + 1
def Qsort(value,l, r, freq):
randindex = random.randint(l, r)
nums[l], nums[randindex] = nums[randindex], nums[l]
right, pivot = l, r
for i in range(l , r):
if freq.get(value[i]) >= freq.get(value[pivot]):
value[i], value[right] = value[right], value[i]
right += 1
value[right], value[pivot] = value[pivot], value[i]
return right
print(topKfrequence(nums, k))
# 3.按照字符出现次数对字符串排序
def freq_sort(self):
freq = collections.Counter(s)
dic = []
for key,value in freq.items():
dic.append((key, value))
dic.sort(key = lambda x:x[1], reverse = True)
# print(dic)[('b', 2), ('A', 1), ('a', 1)]
ans = []
for i in dic:
if i[1] > 1:
# ('b', 2 )若出现频次大于1,则输出i[1]个i[0]
ans.append(i[0]*i[1])
else:
ans.append(i[0])
print('the sorted str is', '-'.join(ans))
return ''.join(ans)
# 4.颜色分类
def color_sort(self):
l, r = 0, len(color) - 1
i = 0
while i <= r:
while color[i] == 2 and i <= r:
color[i], color[r] = color[r], color[i]
r -= 1
if color[i] == 0:
color[i], color[l] = color[l], color[i]
l += 1
i += 1
print('the sorted color is', color)
return color
if __name__ == "__main__":
# 选择排序、快速排序法参数
nums = [3, 1, 6, 6, 6, 5, 4, 5, 2]
k = 2
# 3.按照字符出现次数对字符串排序参数
s = 'Aabb'
# 4.颜色分类参数
color = [2, 0, 2, 1, 1, 0]
sort_algrm = sort_algrms(nums, k, s, color)
# 选择排序法调用
# sort_algrm.selected_sort()
# 2.出现频率最高的前k个元素
# 方法一:快速排序法
# sort_algrm.findKthLargest()
sort_algrm.topKfreq_Qsort()
# 方法二:堆排序
#sort_algrm.findKthLargest_heapsort()
# 桶排序找出现频次前k次多的元素
# sort_algrm.topKFrequent()
# 3.按照字符出现次数对字符串排序
# sort_algrm.freq_sort()
# 4.颜色分类参数
# sort_algrm.color_sort()
# # 简单递归
# def countdown(i):
# print(i)
# 基线条件
# if i <= 0:
# return False
# 递归条件
# else:
# countdown(i - 1)
#
# i = 5
# countdown(i)
""" 快速排序 o(n * log(n))
# QSort
nus = [4, 5, 1, 2, 3, 5, 4, 1]
# left,right分别为子数组中第一个元素和最后一个元素在原数组中的位置
def QSort(left, right):
# 边界条件
if left >= right:
return -1
# 初始化左右指针的初始值
l, r, key = left, right, nus[left]
# 调整元素的位置
while l < r:
while l < r and nus[r] >= key:
r -= 1
nus[l] = nus[r]
while l < r and nus[l] <= key:
l += 1
nus[r] = nus[l]
# 把基准值赋给左右指针共同指向的位置
nus[r] = key
# 对左侧数组排序
QSort(left, l - 1)
# 对右侧数组排序
QSort(l + 1, right)
QSort(0, len(nus) - 1)
print(nus)
"""