排序专题1 - leetcode215. TopK/347. Top K Frequent Elements/451. Sort Characters By Frequency

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值