程序员代码面试指南刷题--第八章.打印N个数组整体最大的Top K

题目描述
有N个长度不一的数组,所有的数组都是有序的,请从大到小打印这N个数组整体最大的前K个数。
例如,输入含有N行元素的二维数组可以代表N个一维数组。
219, 405, 538, 845, 971
148, 558
52, 99, 348, 691
再输入整数k=5,则打印:
Top 5: 971, 845, 691, 558, 538
[要求]
时间复杂度为O(klogk),空间复杂度为O(klogk)

输入描述:

第一行两个整数T, K。分别表示数组个数,需要打印前K大的元素
接下来T行,每行输入格式如下:
开头一个整数N,表示该数组的大小,接下来N个已排好序的数表示数组内的数

输出描述:

从大到小输出输出K个整数,表示前K大。

示例1

输入

3 5
5 219 405 538 845 971
2 148 558
4 52 99 348 691

输出

971 845 691 558 538

解法一:大根堆

注意:新建结构记录信息!!的做法

import java.io.*;
import java.util.*;
public class Main{
    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] info = br.readLine().trim().split(" ");
        int num = Integer.parseInt(info[0]);
        int k = Integer.parseInt(info[1]);
        int[][] arr = new int[num][];
        for(int i=0;i<num;i++){
            String[] ss = br.readLine().trim().split(" ");
            arr[i] = new int[ss.length];
            for(int j=0;j<ss.length;j++){
                arr[i][j] = Integer.parseInt(ss[j]);
            }
        }
        String res = getRes(arr,k);
        System.out.println(res);
    }
    public static String getRes(int[][] arr,int k){
        if(arr==null||arr.length==0) return null;
        int nums = arr.length;
        Heap[] heap = new Heap[nums];
        for(int i=0;i<nums;i++){
            int val = arr[i][arr[i].length-1];
            //记录是哪一个数组,索引位置和值
            Heap node = new Heap(i,arr[i].length-1,val);
            heap[i] = node;
            heapInsert(heap,i);
        }
        int heapend = heap.length-1;
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<k;i++){
            Heap node = heap[0];
            sb.append(node.val+" ");
            int num = node.num;
            int index = node.index;
            if(index>0){
                heap[0] = new Heap(num,index-1,arr[num][index-1]);
                heapfy(heap,heapend);
            }else{
                if(heapend<=0){
                    throw new RuntimeException("数不够");
                }
                heap[0] = heap[heapend];
                heapfy(heap,--heapend);
            }
        }
        return sb.toString().trim();
    }
    public static void heapfy(Heap[] heap,int heapend){
        int left = 1;
        int right = 2;
        int index = 0;
        int largest = index;
        while(left<=heapend){
            if(heap[left].val>heap[index].val){
                largest = left;
            }                 
            if(right<=heapend&&heap[right].val>heap[largest].val){
                largest = right;
            }
            if(largest!=index){
                swap(heap,index,largest);
            }else{
                break;
            }
            left = largest*2+1;
            right = largest*2+2;
        }
    }
    public static void heapInsert(Heap[] heap,int index){
        while(index>0){
            int parent = (index-1)/2;
            if(heap[parent].val<heap[index].val){
                swap(heap,parent,index);
                index = parent;
            }else{
                break;
            }
        }
    }
    public static void swap(Heap[] heap,int i,int j){
        Heap tmp = heap[i];
        heap[i] = heap[j];
        heap[j] = tmp;
    }
}
class Heap{
    int num;
    int index;
    int val;
    public Heap(int num,int index,int val){
        this.num = num;
        this.index = index;
        this.val = val;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值