[算法]打印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,961,558,538。

要求:

1.如果所有数组的元素个数小于K,则从小到大打印所有的数。

2.时间复杂度为O(KlogN)。

解答:

利用堆结构和堆排序完成。


import java.util.Arrays;

public class Problem_20_PrintMaxTopK {

	public static class HeapNode {
		public int value;
		public int arrNum;
		public int index;

		public HeapNode(int value, int arrNum, int index) {
			this.value = value;
			this.arrNum = arrNum;
			this.index = index;
		}
	}

	public static void printTopK(int[][] matrix, int topK) {
		int heapSize = matrix.length;
		HeapNode[] heap = new HeapNode[heapSize];
		for (int i = 0; i != heapSize; i++) {
			int index = matrix[i].length - 1;
			heap[i] = new HeapNode(matrix[i][index], i, index);
			heapInsert(heap, i);
		}
		System.out.println("TOP " + topK + " : ");
		for (int i = 0; i != topK; i++) {
			if (heapSize == 0) {
				break;
			}
			System.out.print(heap[0].value + " ");
			if (heap[0].index != 0) {
				heap[0].value = matrix[heap[0].arrNum][--heap[0].index];
			} else {
				swap(heap, 0, --heapSize);
			}
			heapify(heap, 0, heapSize);
		}
	}

	public static void heapInsert(HeapNode[] heap, int index) {
		while (index != 0) {
			int parent = (index - 1) / 2;
			if (heap[parent].value < heap[index].value) {
				swap(heap, parent, index);
				index = parent;
			} else {
				break;
			}
		}
	}

	public static void heapify(HeapNode[] heap, int index, int heapSize) {
		int left = index * 2 + 1;
		int right = index * 2 + 2;
		int largest = index;
		while (left < heapSize) {
			if (heap[left].value > heap[index].value) {
				largest = left;
			}
			if (right < heapSize && heap[right].value > heap[largest].value) {
				largest = right;
			}
			if (largest != index) {
				swap(heap, largest, index);
			} else {
				break;
			}
			index = largest;
			left = index * 2 + 1;
			right = index * 2 + 2;
		}
	}

	public static void swap(HeapNode[] heap, int index1, int index2) {
		HeapNode tmp = heap[index1];
		heap[index1] = heap[index2];
		heap[index2] = tmp;
	}

	public static int[][] generateRandomMatrix(int maxRow, int maxCol,
			int maxValue) {
		if (maxRow < 0 || maxCol < 0) {
			return null;
		}
		int[][] matrix = new int[(int) (Math.random() * maxRow) + 1][];
		for (int i = 0; i != matrix.length; i++) {
			matrix[i] = new int[(int) (Math.random() * maxCol) + 1];
			for (int j = 0; j != matrix[i].length; j++) {
				matrix[i][j] = (int) (Math.random() * maxValue);
			}
			Arrays.sort(matrix[i]);
		}
		return matrix;
	}

	public static void printMatrix(int[][] matrix) {
		for (int i = 0; i != matrix.length; i++) {
			for (int j = 0; j != matrix[i].length; j++) {
				System.out.print(matrix[i][j] + " ");
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
		int[][] matrix = generateRandomMatrix(5, 10, 1000);
		printMatrix(matrix);
		System.out.println("===========================");
		printTopK(matrix, 100);
	}

}

时间: 2024-08-05 23:40:35

[算法]打印N个数组的整体最大Top K的相关文章

数组元素整体移动问题的研究

问题介绍 有一类问题是,将数组进行整体平移,例如整体向左或向右平移3个长度,类似于这类问题的解决方案很多,下面就来尝试使用Java语言给出三种解决方法,设想问题是将一个数组整体向右平移k个单位,即若平移前数组为{1,2,3,4,5,6,7},平移3个长度后数组为{5,6,7,1,2,3,4}. 朴素思想 一般,最朴素的方法是先创建一个新数组,然后按规律将数组一一赋值即可.如下代码所示: /** * 最朴素的算法,开辟另一个数字,拷贝进去就是了 * @param a 输入数组 * @param k

顺时针和逆时针螺旋打印二维数组(行列式)

一.要求: 行列式,行和宽不一定相等,要求顺时针螺旋打印每一个元素,所谓顺时针螺旋即: 第一圈:从第一行第一列元素开始,先从左到右打印第一行所有元素,接着打印最后一剩余列元素,再从右到左打印最后一行剩余元素,接着从下到上打印第一列剩余元素 第二圈:从第二行第二列开始,按上面的顺时针顺序打印一圈元素 ...,一圈圈反复,直到把所有元素无重复的打印完. 逆时针螺旋与上面的顺序刚好相反. 二.分析: 顺时针螺旋打印可以将问题分割为:先按顺时针打印第一圈,再按顺时针打印第二圈,其中每圈又分四个步骤:从左

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

编程算法 - 数字在排序数组中出现的次数 代码(C)

数字在排序数组中出现的次数 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 统计一个数字在排序数组中出现的次数. 通过折半查找, 找到首次出现的位置, 再找到末次出现的位置, 相减即可. 时间复杂度O(logn). 代码: /* * main.cpp * * Created on: 2014.6.12 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #include <stdio.h> #inc

KMP算法 --- 深入理解next数组

KMP算法的前缀next数组最通俗的解释 我们在一个母字符串中查找一个子字符串有很多方法.KMP是一种最常见的改进算法,它可以在匹配过程中失配的情况下,有效地多往后面跳几个字符,加快匹配速度. 当然我们可以看到这个算法针对的是子串有对称属性,如果有对称属性,那么就需要向前查找是否有可以再次匹配的内容. 在KMP算法中有个数组,叫做前缀数组,也有的叫next数组,每一个子串有一个固定的next数组,它记录着字符串匹配过程中失配情况下可以向前多跳几个字符,当然它描述的也是子串的对称程度,程度越高,值

KMP算法中求next数组的实质

在串匹配模式中,KMP算法较蛮力法是高效的算法,我觉得其中最重要的一点就是求next数组: 看了很多资料才弄明白求next数组是怎么求的,我发现我的忘性真的比记性大很多,每次看到KMP算法求next数组都得花很长时间去看怎么求,虽然看了很多遍了,但还是容易忘,所以我今天非得把它记下来,这样我下次看到的时候就可以直接看我的总结了,哈,可恶的记性,总是这么不争气.设目标串为S,需要匹配串为T: next[j]数组生成的实质:     next[j]数组的值其实就等于串T1T2...Tj-1中相同的前

算法(1)数组

写在前面:研究操作系统,习惯了用C,但是在做算法题甚至构建大型系统时,C真的是噩梦.还是用C++比较好,基本算法很成熟,并可基于此实现更复杂的算法.那就边写算法边捡起来好久不用的C++吧! 题目:数组中的k差对(K-diff Pairs).输入为一个数组A和一个整数k,找到数组中 所有的数值对pairs(i,j),其中A[i]和A[j]之间差的绝对值是k.比如[3,1,4,1,5],k=2,ouput=2,这样的差值对是(1,3)和(3,5),其中1虽然在数组中出现过2次,但是只算一次.(题目:

1142: 零起点学算法49——找出数组中最大元素的位置(下标值)

1142: 零起点学算法49--找出数组中最大元素的位置(下标值) Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 1937  Accepted: 977[Submit][Status][Web Board] Description 找出数组中最大的元素的下标. Input 多组测试,每组先输入一个不大于10的整数n 然后是n个整数 Output 输出这n个整数中最大的元素及下标值 Sample I

一个for循环打印二维数组

#include<stdio.h> #define MAXX 2 #define MAXY 3 void printarray() { int Arr[MAXX][MAXY] = {1,2,3,4,5,6}; for(int i = 0;i< MAXX*MAXY;i++) { printf("%d\n",Arr[i/MAXY][i%MAXY]); ///注意,一直没管MAXX什么事,在计算这一类的时候,最容易出问题 } } 一个for循环打印二维数组