Given a non-empty array of integers, return the k most frequent elements.
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]Example 2:
Input: nums = [1], k = 1
Output: [1] Note:You may assume k is always valid, 1 ≤ k ≤ number of unique elements. Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
//good example for bucket sort
namespace SortingQuestions
{
/// <summary>
/// https://leetcode.com/explore/interview/card/top-interview-questions-medium/110/sorting-and-searching/799
/// </summary>
[TestClass]
public class TopKFrequentTest
{
[TestMethod]
public void SimpleUseCaseTest()
{
int[] nums = { 1, 1, 1, 2, 2, 3 };
int k = 2;
int[] expected = { 1, 2 };
CollectionAssert.AreEqual(expected, TopKFrequentClass.TopKFrequent(nums, k).ToArray());
}
}
public class TopKFrequentClass
{
public static IList<int> TopKFrequent(int[] nums, int k)
{
Dictionary<int, int> number2Count = new Dictionary<int, int>();
//we count how many times each number appears
foreach (var num in nums)
{
number2Count.TryGetValue(num, out var temp);
number2Count[num] = temp + 1;
}
List<int>[] bucket = new List<int>[nums.Length + 1];
//we allocate an array in the size of the original list of numbers
//we iterate all of the numbers and for add each number to the index in the array
// the index represents how many times that number appeared
//
// 0 times -> none
// 1 times -> number 3
// 2 times -> number 2
// 3 times -> number 1
// 4 times -> none
// 5 times -> none
foreach (var key in number2Count.Keys)
{
int frequency = number2Count[key];
if (bucket[frequency] == null)
{
bucket[frequency] = new List<int>();
}
bucket[frequency].Add(key);
}
List<int> result = new List<int>();
// we iterate the list bucket in reverse until the number of items in the result
// list equals k, because we iterate in reserve we get the biggest numbers
for (int pos = bucket.Length - 1; pos >= 0 && result.Count < k; pos--)
{
if (bucket[pos] != null)
{
result.AddRange(bucket[pos]);
}
}
return result;
}
}
}
I really like this question and it took me some time to understand how to implement the bucket sorting.
I know I can also use MaxHeap. Since C# doesn't have a MaxHeap, do you think using a SortedList can help here somehow with the performance? (remember the question limitations)
I am mainly looking for performance optimizations.