堆应用—TopK问题

解决Topk问题思路一般有两种:
找100亿个元素里面的前1000大个元素

 1.将所有的元素放进数组里,调整为大堆,依次遍历1000次输出堆顶元素。
 2.创建一个size为1000的数组,将1000个元素放进该数组中,并调整为小堆,堆顶元素可视为守门员,依次遍历剩余元素和当前堆顶元素进行比较,若大于堆顶元素则将堆顶元素删除,将当前元素尾插入堆,再向上调整为小堆,循环比较。

当所给元素过多时,一般使用第二种思路。一般1亿个元素占内存的100mb。

力扣373
题目描述:给定两个以升序排列的整形数组 nums1 和 nums2, 以及一个整数 k。
定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2。
找到和最小的 k 对数字 (u1,v1), (u2,v2) … (uk,vk)。
在这里插入图片描述在这里插入图片描述在这里插入图片描述
思路:创建一个pair将数值对保存,并继承一个comparaTo接口用来比较排序。采用上述的第一种思路将所有元素放进队列里,调整为一个小堆(基于comparaTo),再循环K次取出队首元素,则为所求。记得考虑合法性校验。

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;

class Pair implements Comparable<Pair>{
    public int n1;
    public int n2;
    public int sum=n1+n2;

        public Pair(int n1, int n2) {
            this.n1 = n1;
            this.n2 = n2;
            this.sum = n1+n2;
        }

    @Override
    //用comparaTo接口实现对pair里数对的排序,也就是实现小堆操作
    public int compareTo(Pair o){
      //如果this比other大,就返回>0
      // 如果this比other小,就返回<0
       //如果this比other大,就返回=0
        //此处直接用sum值来衡量pair的大小
        return this.sum-o.sum;
    }
}
public class TopK {
    //返回值形如二维数组,一行就是一对数,总共有k行
    // [
    // [num1,num2]
    // [num1,num2]
    // ]
    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
      List<List<Integer>> result=new ArrayList<>();
    //先对不合法情况进行校验
        if (nums1==null||nums2==null||k<=0){
            return result;
        }
        //采用第一种思路,将所有数对放置队列中,将队列调整为一个小堆,再循环取出k个队首元素
        //调用标准库中的优先级队列
        PriorityQueue<Pair> queue=new PriorityQueue<>();
        for (int i=0;i<nums1.length;i++){
            for (int j=0;j<nums2.length;j++){
                queue.offer(new Pair(nums1[i],nums2[j]));
            }
        }
        //循环结束后,此时所有的数对都在队列中,此时循环k次取出队首元素,加入result即为所求
        //注意:这里要考虑若queue的size小于k值,则输出所有元素,对应示例3,记得考虑
        for (int i=0;i<k&&!queue.isEmpty();i++){//注意是i<k,不是i<=k
            Pair cur=queue.poll();//poll出来的值是数对
            List<Integer> temp=new ArrayList<>();
            temp.add(cur.n1);//把这些数值对先加到一维数组里面
            temp.add(cur.n2);
            result.add(temp);//再将一维数组加到二维数组里面
        }
      return result;
    }



}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值