239. 滑动窗口最大值
思路: 单调队列
其实队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队里里的元素数值是由大到小的。
public class Solution {
public int[] MaxSlidingWindow(int[] nums, int k) {
List<int> result = new List<int>();
Queue queue = new Queue();
for (int i = 0; i < k; i++)
{
queue.Push(nums[i]);
}
result.Add(queue.Peek());
for (int i = k; i < nums.Length; i++)
{
queue.Push(nums[i]);
queue.Pop(nums[i - k]);
result.Add(queue.Peek());
}
return result.ToArray();
}
}
public class Queue
{
LinkedList<int> _queue = new LinkedList<int>();
public void Push(int val)
{
while (_queue.Count > 0 && _queue.Last.Value < val)
{
_queue.RemoveLast();
}
_queue.AddLast(val);
}
public void Pop(int val)
{
if (_queue.Count > 0 && _queue.First.Value == val)
{
_queue.RemoveFirst();
}
}
public int Peek()
{
return _queue.First.Value;
}
}
347. 前 K 个高频元素
法一思路: 用小顶堆,因为要统计最大前k个元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前k个最大元素。每次只排序k个元素,时间复杂度为O(nlogk)
//only .NET 7 and .NET 6 have PriorityQueue<TElement,TPriority>()
public int[] TopKFrequent(int[] nums, int k)
{
Dictionary<int, int> dict = new Dictionary<int, int>();
for (int i = 0; i < nums.Length; i++)
{
if (dict.ContainsKey(nums[i]))
{
dict[nums[i]]++;
}
else
{
dict.Add(nums[i], 1);
}
}
PriorityQueue<int, int> pq = new PriorityQueue<int, int>();
foreach (KeyValuePair<int, int> pair in dict)
{
pq.Enqueue(pair.Key, pair.Value);
if (pq.Count > k)
{
pq.Dequeue();
}
}
int[] result = new int[k];
for (int i = k - 1; i >= 0; i--)
{
result[i] = pq.Peek();
pq.Dequeue();
}
return result;
}
法二思路: 最大出现频率是nums.length, 最小出现频率是1,用数组存,数组下标对应出现频率,数组值为出现同样次数的元素list。
public int[] TopKFrequent(int[] nums, int k) {
IDictionary<int, int> dict = new Dictionary<int, int>();
for (int i = 0; i < nums.Length; i++)
{
if (dict.ContainsKey(nums[i]))
{
dict[nums[i]]++;
}
else
{
dict.Add(nums[i], 1);
}
}
List<int>[] data = new List<int>[nums.Length+1];
foreach (KeyValuePair<int, int> kvp in dict)
{
if (data[kvp.Value] == null)
{
data[kvp.Value] = new List<int>();
}
data[kvp.Value].Add(kvp.Key);
}
int count = k;
List<int> result = new List<int>();
for (int i = nums.Length; i >= 0 && count > 0; i--)
{
if (data[i] != null && data[i].Count > 0)
{
result.AddRange(data[i]);
count-= data[i].Count;
}
}
return result.ToArray();
}