Java 从不同文件夹中存在的所有文件中查找100个最大数字
我最近接受了一次采访,在采访中,我被问到了下面的问题,这对我来说听起来很容易,但最后对我来说变得很棘手 所有文件夹及其子文件夹中都有大量文件。每个 文件的每一行都有很多数字。给定一个根文件夹,我需要找到100个最大的 所有这些文件中的数字。我提出了以下解决方案:Java 从不同文件夹中存在的所有文件中查找100个最大数字,java,algorithm,data-structures,Java,Algorithm,Data Structures,我最近接受了一次采访,在采访中,我被问到了下面的问题,这对我来说听起来很容易,但最后对我来说变得很棘手 所有文件夹及其子文件夹中都有大量文件。每个 文件的每一行都有很多数字。给定一个根文件夹,我需要找到100个最大的 所有这些文件中的数字。我提出了以下解决方案: 逐行读取所有文件 将每个数字存储在数组列表中 按降序排序 现在从列表中获取前k个数字 但后来面试官问我这件事的时间复杂度是多少。我说,因为我们正在对它进行排序,所以它将是O(nlogn),然后他问我们如何改进下面的程序?既然您将所有
- 逐行读取所有文件
- 将每个数字存储在数组列表中
- 按降序排序
- 现在从列表中获取前k个数字
private static final List<Integer> numbers = new ArrayList<>();
public static void main(String[] args) {
int k = 100;
List<Integer> numbers = findKLargest("/home/david");
// sort in descending order
Collections.sort(numbers, Collections.reverseOrder());
List<Integer> kLargest = new ArrayList<>();
int j = 0;
// now iterate all the numbers and get the first k numbers from the list
for (Integer num : numbers) {
j++;
kLargest.add(num);
if (j == k) {
break;
}
}
// print the first k numbers
System.out.println(kLargest);
}
/**
* Read all the numbers from all the files and load it in array list
* @param rootDirectory
* @return
*/
private static List<Integer> findKLargest(String rootDirectory) {
if (rootDirectory == null || rootDirectory.isEmpty()) {
return new ArrayList<>();
}
File file = new File(rootDirectory);
for (File entry : file.listFiles()) {
if (entry.isDirectory()) {
numbers.addAll(findKLargest(entry.getName()));
} else {
try (BufferedReader br = new BufferedReader(new FileReader(entry))) {
String line;
while ((line = br.readLine()) != null) {
numbers.add(Integer.parseInt(line));
}
} catch (NumberFormatException | IOException e) {
e.printStackTrace();
}
}
}
return numbers;
}
private static final List number=new ArrayList();
公共静态void main(字符串[]args){
int k=100;
列表编号=findk最大(“/home/david”);
//按降序排序
Collections.sort(数字,Collections.reverseOrder());
List kLargest=new ArrayList();
int j=0;
//现在迭代所有数字并从列表中获得前k个数字
for(整数编号:数字){
j++;
kLargest.add(num);
如果(j==k){
打破
}
}
//打印前k个数字
系统输出打印LN(kLargest);
}
/**
*从所有文件中读取所有数字并将其加载到数组列表中
*@param rootDirectory
*@返回
*/
私有静态列表(字符串根目录){
if(rootDirectory==null | | rootDirectory.isEmpty()){
返回新的ArrayList();
}
File File=新文件(根目录);
对于(文件条目:File.listFiles()){
if(entry.isDirectory()){
addAll(findkmax(entry.getName());
}否则{
try(BufferedReader br=new BufferedReader(new FileReader(entry))){
弦线;
而((line=br.readLine())!=null){
add(Integer.parseInt(line));
}
}捕获(NumberFormatException | IOE异常){
e、 printStackTrace();
}
}
}
返回号码;
}
与存储所有N(所有文件中数字的总计数)值并对其进行排序不同,您只能存储100个值—每个时刻最大的值
此任务的方便快捷的数据结构-(通常基于)。创建min-第一个值为100的堆,然后针对每个新值检查其是否大于堆顶。如果是-移除顶部,插入新项目
空间复杂度是O(K)
,时间复杂度是O(NlogK)
,这里K=100
,因此复杂度可以评估为O(1)
和O(N)
(省略常数项)
演示其工作原理的Python示例:
import heapq, random
pq = [random.randint(0, 20) for _ in range(5)] #initial values
print(pq)
heapq.heapify(pq) #initial values ordered in heap
print(pq)
for i in range(5):
r = random.randint(0, 20) # add 5 more values
if r > pq[0]:
heapq.heappop(pq)
heapq.heappush(pq, r)
print(r, pq)
[17, 22, 10, 1, 15] //initial values
[1, 15, 10, 22, 17] //heapified, smallest is the left
29 [10, 15, 17, 22, 29] //29 replaces 1
25 [15, 22, 17, 29, 25] //25 replaces 10
14 [15, 22, 17, 29, 25] //14 is too small
8 [15, 22, 17, 29, 25] //8 is too small
21 [17, 21, 25, 29, 22] //21 is in the club now
添加到@MBo中,Java实现如下所示 使用 使用大小为100的优先级队列创建最小堆
int MAX = 100;
PriorityQueue<Integer> queue = new PriorityQueue<>(MAX);
int MAX=100;
PriorityQueue=新的PriorityQueue(最大值);
从文件中读取数字,插入并平衡最小堆。将min堆中的minValue与newValue进行比较。如果较大,则删除minValue并插入newValue
public void balanceMinHeap(int newValue) {
if(queue.size() < MAX) {
queue.add(newValue);
return;
}
if(queue.peek() < newValue) {
queue.remove();
queue.add(newValue);
}
}
public void balanceMinHeap(int newValue){
if(queue.size()
现在您可以从最小堆中以升序获得100个最大数
for(int i=0;i<100;i++) {
System.out.println(queue.remove());
}
用于(int i=0;i您只需要存储100个最大的数字。如果新数字较小,则忽略其中最小的数字。如果不这样做,则删除数组中的最小数字并添加新数字。您可能希望保持数组排序。谷歌用于插入排序。它需要堆:您的示例的另一个问题是,可能有超过内存容量的数字。@MNo但假设在队列中,倒数第二个是105,最后是102,然后下一个值是110,那么在这种情况下,它应该替换为顶部,然后向前移动?@Shivang Agarwal是的。我们删除最小值102,插入110,然后105变为新值top@MNo这将由二进制堆或优先级队列处理?@Shivang Agarwal二进制堆是一种优先级队列实现(简单且流行),所以说“二进制堆”,我们假设“优先级队列”@MBo这里N是文件数,对吗?您能否提供一个如何使用“优先级队列”实现的示例?
Comparator<Integer> desendingOrder = new Comparator<Integer>() {
public int compare(Integer x, Integer y) {
return y - x;
}
};
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(MAX, desendingOrder);
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(MAX, Collections.reverseOrder());