当前位置: 首页 > 知识库问答 >
问题:

从不同文件夹中的所有文件中找到100个最大数字

汤枫涟
2023-03-14

我最近接受了一次面试,在面试中,我被问到了下面的问题,这对我来说听起来很容易,但最后对我来说变得很棘手。

所有文件夹及其子文件夹中都有大量文件。每个文件的每一行都有很多数字。给定一个根文件夹,我需要从所有这些文件中找到100个最大的数字。我想出了以下解决方案

  • 逐行读取所有文件。
  • 将每个数字存储在数组列表中。
  • 按降序排序。
  • 现在从列表中获取前k个数字。

但是后来面试官问我这个的时间复杂度是多少。我说既然我们正在对其进行排序,那么它将是O(nlogn),然后他问我们如何改进以下程序?既然你将所有内容存储在内存中,然后对其进行排序——如果你不能将所有内容都放入内存中怎么办?

我当时一头雾水,想不通有没有更好/更高效的方法来解决下面的问题,他想让我写高效的代码,有没有更好的方法来完成这件事?

以下是我想出的原始代码:

  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;
  }

共有2个答案

郎星汉
2023-03-14

添加到@MBo中,Java实现如下

使用PriorityQueue

使用大小为100的优先级队列创建最小堆

int MAX = 100;
PriorityQueue<Integer> queue = new PriorityQueue<>(MAX);

从文件中读取数字,插入并平衡最小堆。将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);
    }

}

现在可以从最小堆中按升序获得100个最大数

    for(int i=0;i<100;i++) {
        System.out.println(queue.remove());
    }

如果您想要降序相同的100个最大数字,只需将相同的队列转换为max-Heap(即,再次是PriorityQueue)

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());
籍光熙
2023-03-14

与存储所有N(所有文件中的数字总数)值并对其进行排序不同,您只能存储100个值—每个时刻最大的值。

此任务优先级队列的方便快捷的数据结构(通常基于二进制堆)。使用100个第一个值创建min-heap,然后对于每个新值检查它是否大于堆top。如果是-删除top,插入新项目。

空间复杂度为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
 类似资料:
  • 我只需要将构建文件夹中的文件(和子文件夹)复制到..html中。 是我遗漏了什么还是我必须一个一个地复制每个文件?

  • 问题内容: 尝试将文件从一个文件夹复制到现有容器文件夹时,我是否丢失了某些内容: 文件 我想将build(host)文件夹中的文件复制到容器中的html: 要清楚;我需要从主机复制到容器。 但是它将复制整个构建文件夹并将其复制到..html / build 我只需要将build文件夹中的文件(和子文件夹)复制到..html中。 我是否缺少某些内容,还是必须一个一个地复制每个文件? 问题答案: 这是

  • 问题内容: 在Linux机器上,我想遍历文件夹层次结构并获取其中所有不同文件扩展名的列表。 从外壳实现这一目标的最佳方法是什么? 问题答案: 试试这个(不确定这是否是最好的方法,但是可以用): 它的工作方式如下: 查找当前文件夹中的所有文件 打印文件扩展名(如果有) 制作唯一的排序列表

  • 文件名的开始是相同的,但结束是动态的,每次我点击下载时都会改变 我所做的: 你能帮忙吗

  • 本文向大家介绍编程题:写一个函数,找到一个文件夹下所有文件,包括子文件夹相关面试题,主要包含被问及编程题:写一个函数,找到一个文件夹下所有文件,包括子文件夹时的应答技巧和注意事项,需要的朋友参考一下 考察点:遍历  

  • 问题内容: 我如何返回一个包含该文件夹中的所有文件以及子文件夹的文件数组,我的方法仅适用于该文件夹,并且不包括子文件夹。 问题答案: 使用您当前的代码,进行以下调整: