Leetcode————347题前K个高频元素的三种解法

解法一

利用字典统计次数 并排序 然后输出结果

字典统计:统计出每个元素的次数,大家千万注意到一旦涉及到关于次数的问题,一般都是用字典或者哈希表c#中一般就直接用字典更方便

Dictionary<int,int> mydic = new Dictionary<int,int>();
for (int i = 0; i < nums.Length; i++)
{
    if (mydic.ContainsKey(nums[i]))
    {
        mydic[nums[i]]++;
    }
    else
    {
        mydic[nums[i]] = 1;
    }
}

排序输出结果:

var list = mydic.Keys.ToList();
list.Sort((a, b) => mydic[b].CompareTo(mydic[a]));//自定义排序算法 降序排序
return list.Take(k).ToArray();//取前K个

解法二:

利用字典计数+小根堆

        先将每个元素出现的频数记录在字典中,然后通过不断的往小根堆中添加,直到添加至最后一个元素频数,每次维护K个元素在小根堆中,即小根堆,保留的就是最大的K个元素的频数,最后直接出队列就行

        核心算法,如果你的语言不自带小根堆,需自己手动实现。

var heap = new PriorityQueue<int,int>();
foreach (var pair in mydic)
{
    heap.Enqueue(pair.Key, pair.Value);
    if(heap.Count>k) heap.Dequeue();
}

int[] result = new int[k];
for (int i = 0; i < k; i++)
{
    result[i] = heap.Dequeue();
}
return result;

方法三

利用字典计数加桶排序

思路:字典记录下元素频数后,维护一个数组,数组中的每个元素为一个列表,每个元素索引记录出现的频数,元素列表记录出现过这么多频数的原数组中的元素(即字典的Key)

①首先建立一个桶数组

var bucket = new List<int>[nums.Length + 1];
foreach (var num in mydic)
{
    int count = num.Value;
    if (bucket[count]==null) bucket[count] = new List<int>();
    bucket[count].Add(num.Key);
}

②你现在维护的这个桶数组,从尾往头看,每个索引对应的 就是频数最大的元素列表,如果当前频数对应的没有列表(即为空),就依次向前走,直到你找到K个元素之后,就直接退出

List<int> result = new List<int>();
for (int i = bucket.Length - 1; i > 0 && result.Count < k; i--)
{
    if (bucket[i] != null)
    {
        foreach (var item in bucket[i])
        {
            result.Add(item);
            if(result.Count==k)
                break;
        }
    }
}
return result.ToArray();

附:整个实现代码

namespace _347_前K个高频元素
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
        public class Solution
        {
            public int[] TopKFrequent(int[] nums, int k)
            {
                Dictionary<int,int> mydic = new Dictionary<int,int>();
                for (int i = 0; i < nums.Length; i++)
                {
                    if (mydic.ContainsKey(nums[i]))
                    {
                        mydic[nums[i]]++;
                    }
                    else
                    {
                        mydic[nums[i]] = 1;
                    }
                }

                //方法三
                //var bucket = new List<int>[nums.Length + 1];
                //foreach (var num in mydic)
                //{
                //    int count = num.Value;
                //    if (bucket[count]==null) bucket[count] = new List<int>();
                //    bucket[count].Add(num.Key);
                //}

                //List<int> result = new List<int>();
                //for (int i = bucket.Length - 1; i > 0 && result.Count < k; i--)
                //{
                //    if (bucket[i] != null)
                //    {
                //        foreach (var item in bucket[i])
                //        {
                //            result.Add(item);
                //            if(result.Count==k)
                //                break;
                //        }
                //    }
                //}
                //return result.ToArray();

                //方法二
                //var heap = new PriorityQueue<int,int>();
                //foreach (var pair in mydic)
                //{
                //    heap.Enqueue(pair.Key, pair.Value);
                //    if(heap.Count>k) heap.Dequeue();
                //}

                //int[] result = new int[k];
                //for (int i = 0; i < k; i++)
                //{
                //    result[i] = heap.Dequeue();
                //}
                //return result;

                //方法一
                var list = mydic.Keys.ToList();
                list.Sort((a, b) => mydic[b].CompareTo(mydic[a]));//自定义排序算法 降序排序
                return list.Take(k).ToArray();//取前K个
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值