215. Kth Largest Element in an Array
题目描述
找出数组中第k大的数。
假设k是有效的,即 1 ≤ k ≤ 数组长度。
例子
Example 1:
Input: [3,2,1,5,6,4] and k = 2
Output: 5
Example 2:
Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4
思想
直接排序,然后取出第k大的数 - 时间复杂度O(nlogn)
(法1 - 快速选择)
快排的思想,每次选定一个基准数,然后将比基准数小的数移到左边,比基准数大的数移到右边… 每次都只考虑一半,直到找到第k个。
[时间复杂度] 我们采用随机选取的pivot,所以平均来看每次pivot都选在中间位置。T(n) = O(n + n/2 + n/4 + … + 2 + 1) = O(2n) = O(n)。
类似于快排,最好O(n),最差O(n^2),平均O(nlogn).
(法2 - 堆排序)
首先建k个元素的小顶堆(堆顶元素最小),时间复杂度O(klogk)。然后,剩余的(n-k)个元素依次与堆顶元素x比较,大于x则替换,小于x则忽略;更新堆O(logk)。最后取堆顶元素,即为第k大的数。
总时间复杂度O(klogk+(n-k)logk) = O(nlogk)
解法1
快速选择。复杂度:时间O(n),空间O(1)
from random import randint
class Solution(object):
def findKthLargest(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
pos = self.quickSort(nums, 0, len(nums)-1)
while pos != len(nums)-k:
if pos > len(nums)-k:
pos = self.quickSort(nums, 0, pos-1)
else:
pos = self.quickSort(nums, pos+1, len(nums)-1)
return nums[pos]
def quickSort(self, nums, left, right):
pivot = randint(left, right)
# 把基准数放到最后
number = nums[pivot]
nums[pivot], nums[right] = nums[right], nums[pivot]
# 初始化pos, 指向第一个≥基准数的位置
pos = left
for i in range(left, right):
if nums[i] < number:
nums[pos], nums[i] = nums[i], nums[pos]
pos += 1
nums[pos], nums[right] = nums[right], nums[pos]
return pos
解法2
堆排序。复杂度:时间O(nlogk),空间O(k)
import heapq
class Solution(object):
def findKthLargest(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
minHeap = [float('-inf')] * k
for num in nums:
if num > minHeap[0]:
heapq.heappop(minHeap)
heapq.heappush(minHeap, num)
return minHeap[0]
347. Top K Frequent Elements
题目描述
给定非空数组,返回前k个最高频出现的元素。
例子
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
Example 2:
Input: nums = [1], k = 1
Output: [1]
思想
直观想法,字典存储每个元素出现的次数。然后对字典按值(key = dic.get)降序排序,取出前k个。
(改进)对dic排序时可参照Topk。
解法
class Solution(object):
def topKFrequent(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
dic = {}
for num in nums:
if num not in dic:
dic[num] = 1
else:
dic[num] += 1
return sorted(dic, key = dic.get, reverse = True)[:k]
改进:以最小堆为例 ~
import heapq
class Solution(object):
def topKFrequent(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
dic = {}
for num in nums:
if num not in dic:
dic[num] = 1
else:
dic[num] += 1
minHeap = [(float('-inf'), 1)] * k # heapq按x[0]排序
for key, v in dic.items():
if v > minHeap[0][0]:
heapq.heappop(minHeap)
heapq.heappush(minHeap, (v, key))
print(minHeap)
return list(map(lambda x:x[1], minHeap))
451. Sort Characters By Frequency
题目描述
给定字符串,基于字符出现的次数,对其降序排序。
例子
Example 1:
Input:“tree”
Output:“eert”
Explanation:
‘e’ appears twice while ‘r’ and ‘t’ both appear once.
So ‘e’ must appear before both ‘r’ and ‘t’. Therefore “eetr” is also a valid answer.
Example 2:
Input:“cccaaa”
Output:“cccaaa”
Explanation:
Both ‘c’ and ‘a’ appear three times, so “aaaccc” is also a valid answer.
Note that “cacaca” is incorrect, as the same characters must be together.
Example 3:
Input:“Aabb”
Output:“bbAa”
Explanation:
“bbaA” is also a valid answer, but “Aabb” is incorrect.
Note that ‘A’ and ‘a’ are treated as two different characters.
思想
直观想法,字典存储每个元素出现的次数。然后对字典按值降序排序sorted(dic.items(), key = lambda x:x[1], reverse = True),最后拼接出字符串。
解法
class Solution(object):
def frequencySort(self, s):
"""
:type s: str
:rtype: str
"""
dic = {}
for c in s:
if c not in dic:
dic[c] = 1
else:
dic[c] += 1
new = sorted(dic.items(), key = lambda x:x[1], reverse = True)
ss = ''
for c, t in new:
ss += c * t
return ss