由于现在都是是分布式系统,现有k个文件,每个文件个数为n, 每个文件都是按照时间戳排序, 需要把k个文件合并成1个按照时间戳排好序的文件;按照题目写出实现的代码,思考时间复杂度

题目:由于现在都是是分布式系统,现有k个文件,每个文件个数为n,
每个文件都是按照时间戳排序,
需要把k个文件合并成1个按照时间戳排好序的文件;按照题目写出实现的代码,思考时间复杂度

备注:忽略文件读取过程,使用自己熟练的数据结构,编写代码
package com.example.springbootdemo2;

import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.util.JSONPObject;

import java.util.*;

/**
 * @author evanYang
 * @since 2024/2/1 11:35 AM
 */
public class FIleDemo {
    public static void main(String[] args) {
        List<List<Integer>> files = new ArrayList<>();
        
        List<Integer> integers = Arrays.asList(2, 3, 5, 7, 9);
        files.add(integers);
        List<Integer> integers1 = Arrays.asList(1, 1, 1, 2, 2);
        files.add(integers1);
        List<Integer> integers2 = Arrays.asList(2, 4, 6, 8, 10);
        files.add(integers2);
        List<Integer> integers3 = fileMerge(files);
        List<Integer> integers4 = mergeFileDouble(files);
        System.out.println(integers4);
        System.out.println(String.valueOf(integers3));
//        System.out.println(integers3);
//        System.out.println(integers3.toString());
//        System.out.println(Arrays.toString(integers3.toArray()));
    
    }
    
    /*题目:由于现在都是是分布式系统,现有k个文件,每个文件个数为n,
    每个文件都是按照时间戳排序,
    需要把k个文件合并成1个按照时间戳排好序的文件;按照题目写出实现的代码,思考时间复杂度
    
    备注:忽略文件读取过程,使用自己熟练的数据结构,编写代码
    */
    public static List<Integer> fileMerge(List<List<Integer>> files) {
        List<Integer> mergeFile = new ArrayList<>();
        PriorityQueue<Node> minHeap = new PriorityQueue<>(Comparator.comparingInt(Node::getValue));
        //每个文件的 第一元素加入
        for (int i = 0; i < files.size(); i++) {
            List<Integer> file = files.get(i);
            if (!file.isEmpty()) {
                Integer value = file.get(0);
                minHeap.offer(new Node(i, 0, value));
            }
        }
        // 逐个弹出堆顶元素,将最小元素加入合并后的列表,并将来自同一文件的下一个元素加入堆
        while (!minHeap.isEmpty()) {
            Node node = minHeap.poll();
            mergeFile.add(node.getValue());
            int nextIndex = node.getIndex() + 1;
            List<Integer> fileIndex = files.get(node.getFileIndex());
            int size = fileIndex.size();
            if (nextIndex < size) {
                int nextValue = fileIndex.get(nextIndex);
                minHeap.offer(new Node(node.getFileIndex(), nextIndex, nextValue));
            }
        }
        
        return mergeFile;
    }
    
    static class Node {
        private int fileIndex;
        private int index;
        private int value;
        
        public Node(int fileIndex, int index, int value) {
            this.fileIndex = fileIndex;
            this.index = index;
            this.value = value;
        }
        
        public int getFileIndex() {
            return fileIndex;
        }
        
        public int getIndex() {
            return index;
        }
        
        public int getValue() {
            return value;
        }
    }
    
    public static List<Integer> mergeFileDouble(List<List<Integer>> files) {
        List<Integer> mergeResult = new ArrayList<>();
        int[] points = new int[files.size()];
        
        while (true) {
            int min = Integer.MAX_VALUE;
            int minFileIndex = -1;
            for (int i = 0; i < files.size(); i++) {
                List<Integer> file = files.get(i);
                int point = points[i];
                if (point < file.size() && file.get(point) < min) {
                    min = file.get(point);
                    minFileIndex = i;
                }
            }
            
            if (minFileIndex == -1) {
                break;
            }
            mergeResult.add(min);
            points[minFileIndex]++;
        }
        return mergeResult;
    }
    
}

这种方法使用了一个指针数组来记录每个文件当前元素的位置。在每一轮循环中,我们找到当前指针指向的最小元素,并将其添加到合并后的列表中。然后,我们更新该文件的指针,指向下一个元素。当所有文件的指针都超出了文件的长度时,表示合并完成。

这种实现的时间复杂度为O(kn),其中k是文件的个数,n是每个文件的平均元素个数。不使用优先队列的话,在每一轮循环中都需要遍历k个文件来找到最小元素,因此整体复杂度为O(kn)。

初始化堆的过程需要将每个文件的第一个元素加入堆,时间复杂度为O(k)。
在归并的过程中,每个文件的元素最多会被加入和弹出堆一次,所以归并的过程时间复杂度为O(knlogk),其中n是每个文件的平均元素个数。
最后返回合并后的文件列表,时间复杂度为O(kn)。
综上所述,总的时间复杂度为O(knlogk)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值