算法总结

1.数据流的第 K 大数值

设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。

请实现 KthLargest 类:

    KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。
    int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。

题解:就是找一个第k大的元素,可以遍历,或者排序后查找。优解是用一个优先队列自动排序,这个队列维持一个前k大的元素,队头就是第k大元素。比如k=3,那这个队列就是维持一个第一,二,三大的元素。因为自动排序所以队列是第三大元素。是一个递增队列。

package com.chenghaixiang.jianzhi2.day20;

import java.util.ArrayDeque;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 * @author 程海翔
 * @school 石家庄铁道大学
 */
public class Office059 {
    public static void main(String[] args) {
        int[] nums={4, 5, 8, 2};
        KthLargest kthLargest=new KthLargest(1,nums);
        System.out.println(kthLargest.add(3));

    }
}
//设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。
//
//请实现 KthLargest 类:
//
//    KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。
//    int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。

class KthLargest {
    //PriorityQueue是优先队列,作用是保证每次取出的元素都是队列中权值最小的,这里涉及到了大小关系,
    //说白了是自动排序从小到大
    //元素大小的评判可以通过元素自身的自然顺序(使用默认的比较器),也可以通过构造时传入的比较器。
    PriorityQueue<Integer> queue;
    int k;

    public KthLargest(int k, int[] nums) {
        this.k=k;
        queue=new PriorityQueue<>();
        for (int x:nums){
            //调用add函数保证数据流中数据排序
            add(x);
        }
    }

    public int add(int val) {
        queue.offer(val);
        if(queue.size()>k){
            //检索并删除队头
            //维持一个前k大的队列
            //队头就是第k大的值
            queue.poll();
        }
        //检索不删除
        return queue.peek();
    }
}
View Code

2.出现频率最高的 k 个数字

给定一个整数数组 nums 和一个整数 k ,请返回其中出现频率前 k 高的元素。可以按 任意顺序 返回答案。

题解:因为要统计出现频率所以用一个数组存储,用之前的题思路,我们添加这个数组进入一个集合能不能自动排序,但添加的是一个数组,所以要自定义比较器,自定义排序规则(难点)

package com.chenghaixiang.jianzhi2.day20;

import java.util.*;

/**
 * @author 程海翔
 * @school 石家庄铁道大学
 */
public class Office060 {
    public static void main(String[] args) {
        int[] a=new int[]{1,1,1,2,2,3};
        Solution solution=new Solution();
        solution.topKFrequent(a,2);
    }
}
//给定一个整数数组 nums 和一个整数 k ,请返回其中出现频率前 k 高的元素。可以按 任意顺序 返回答案。
class Solution {
    //
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> curr=new HashMap<>();
        for (int num:nums){
            //遍历数组统计各个数字出现的次数
            curr.put(num,curr.getOrDefault(num,0)+1);
        }

        //初始化小顶堆
        // int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
        //new Comparator<int[]>()自定义比较器,比较compare方法中自定义的比较,实现排序
        //堆顶是次数出现最小的值

        PriorityQueue<int[]> queue=new PriorityQueue<>(new Comparator<int[]>() {
            //返回负整数,零或正整数,第一个参数小于,等于或大于第二个参数。
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1]-o2[1];
            }
        });
        for (Map.Entry<Integer,Integer> entry:curr.entrySet()){
            int num=entry.getKey(),count=entry.getValue();
            if(queue.size()==k){
                //保证堆中添加元素出现次数是比队头大
                if(queue.peek()[1]<count){
                    queue.poll();
                    queue.offer(new int[]{num,count});
                }
            }else {
                queue.offer(new int[]{num,count});
            }
        }

        int[] res=new int[k];
        for (int i=0;i<k;++i){
            res[i]=queue.poll()[0];
        }
        return res;
    }
}
View Code

 

posted @ 2022-09-12 22:57  chenghaixinag  阅读(22)  评论(0编辑  收藏  举报