代码随想录算法训练营第十三天|239. 滑动窗口最大值、347. 前 K 个高频元素

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();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值