Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从不同文件夹中存在的所有文件中查找100个最大数字_Java_Algorithm_Data Structures - Fatal编程技术网

Java 从不同文件夹中存在的所有文件中查找100个最大数字

Java 从不同文件夹中存在的所有文件中查找100个最大数字,java,algorithm,data-structures,Java,Algorithm,Data Structures,我最近接受了一次采访,在采访中,我被问到了下面的问题,这对我来说听起来很容易,但最后对我来说变得很棘手 所有文件夹及其子文件夹中都有大量文件。每个 文件的每一行都有很多数字。给定一个根文件夹,我需要找到100个最大的 所有这些文件中的数字。我提出了以下解决方案: 逐行读取所有文件 将每个数字存储在数组列表中 按降序排序 现在从列表中获取前k个数字 但后来面试官问我这件事的时间复杂度是多少。我说,因为我们正在对它进行排序,所以它将是O(nlogn),然后他问我们如何改进下面的程序?既然您将所有

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

所有文件夹及其子文件夹中都有大量文件。每个 文件的每一行都有很多数字。给定一个根文件夹,我需要找到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;
  }
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());