寻找热点数据 | 豆包MarsCode AI刷题

75 阅读3分钟

问题描述

给你一个整数数组 nums 和一个整数 k,请你用一个字符串返回其中出现频率前 k 高的元素。请按升序排列。

你所设计算法的时间复杂度必须优于 O(nlogn),其中 n 是数组大小。

输入

  • nums: 一个正整数数组
  • k: 一个整数

返回

返回一个包含 k 个元素的字符串,数字元素之间用逗号分隔。数字元素按升序排列,表示出现频率最高的 k 个元素。

参数限制

  • 1 <= nums[i] <= 10^4
  • 1 <= nums.length <= 10^5
  • k 的取值范围是 [1, 数组中不相同的元素的个数]
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

测试样例

样例1:

输入:nums = [1, 1, 1, 2, 2, 3], k = 2
输出:"1,2"
元素 1 出现了 3 次,元素 2 出现了 2 次,元素 3 出现了 1 次。因此前两个高频元素是 1 和 2。

样例2:

输入:nums = [1], k = 1
输出:"1"

样例3:

输入:nums = [4, 4, 4, 2, 2, 2, 3, 3, 1], k = 2
输出:"2,4" 元素 4 出现了 3 次,元素 2 出现了 3 次,元素 3 出现了 2 次,元素 1 出现了 1 次。因此前两个高频元素是 2 和 4。

解题思路

题目思路比较简单,可以分为以下两步

  1. 统计频率:首先遍历数组,使用哈希表(或字典)记录每个元素出现的次数。
  2. 排序:利用排序算法对出现次数进行排序,同时保持元素与其出现次数之间的对应关系。

题目中要求算法的时间复杂度优于 O(nlogn),因此在此题中排序算法的选择和实现至关重要,在python语言中,我们可以直接使用sort()函数方便的实现排序,而在Go语言中,在不借助第三方库的基础上,需要我们自己实现排序算法。

此题中可以选择的满足题目要求的排序算法有归并排序希尔排序堆排序快速排序等,在本文中,实现了使用Go语言写的快速排序算法供大家参考。

快速排序也是基于分治法的思想,通过一个基准值将数组分为两部分,左边的部分都比基准值小,右边的部分都比基准值大,然后递归地对这两部分进行排序。

代码实现

题目求解函数

func solution(nums []int, k int) string {
    // 初始化结果字符串切片
    result := []string{}
    // 使用 map 统计每个元素出现的次数
    mp := make(map[int]int)
    for _, value := range nums {
        mp[value] += 1
    }
    
    // 将 map 中的键和值分别存储到两个切片中
    keys := []int{}
    values := []int{}
    for key, value := range mp {
        keys = append(keys, key)
        values = append(values, value)
    }
    
    // 创建一个索引切片,用于保持元素与出现次数的关联
    index := make([]int, len(keys))
    for i := 0; i < len(index); i++ {
        index[i] = i
    }
    
    // 对索引进行快速排序,间接地对出现次数进行了排序
    QuickSort(index, values, 0, len(values)-1)
    
    // 选取前 k 个元素并添加到结果切片中
    for i := 0; i < k; i++ {
        result = append(result, strconv.Itoa(keys[index[i]]))
    }
    
    // 将结果切片转换为由逗号分隔的字符串
    return strings.Join(result, ",")
}

快速排序算法实现

此快排函数实现了在对 nums 数组进行排序的时候,同时将其的索引 index 进行关联。

func QuickSort(index []int, nums []int, start int, end int) {
    if start < end {
        base := nums[start]
        left := start
        right := end
        
        for left < right {
            for left < right && nums[right] <= base {
                right--
            }
            nums[left] = nums[right]
            index[left] = index[right]
            for left < right && nums[left] > base {
                left++
            }
            nums[right] = nums[left]
            index[right] = index[left]
        }
        nums[left] = base
        index[left] = start
        
        // 递归调用,对左右两部分进行排序
        QuickSort(index, nums, start, left-1)
        QuickSort(index, nums, left+1, end)
    }
}