Very Optimized Solution (Beats 100%) With Explanation || Time Complexity = O(N logN) 
Code
\n\n# Code\n```\nclass Solution {\n    public double maxAverageRatio(int[][] classes, int extraStudents) {\n        // First Store the number of classes in n.\n        int n = classes.length;\n\n        /* Now make a MaxHeap of Pairs.\n         * A Pair will store the index and the change in the pass ratio of that class after adding a brilliant student.\n         * And the Heap will be updated based on change. */\n        PriorityQueue<Pair> heap = new PriorityQueue<>();\n\n        // Now loop over classes and add them in heap.\n        for (int i = 0; i < n; i++){\n            // Calculate the amount of change\n            double change = divide(classes[i][0] +1, classes[i][1] +1) \n                                - divide(classes[i][0], classes[i][1]);\n\n            // Now make a new Pair and put change and index in it\n            Pair pair = new Pair(change, i);\n            \n            // Now add the Pair in heap;\n            heap.add(pair);\n        }\n\n        // Now Make a loop and Run it for the extraStudents numbers of time\n        for (int i = 1; i <= extraStudents; i++) {\n            Pair pair = heap.poll();\n\n            // Update the Heap and also the Classes Array\n            heap.add(update(classes, pair));\n        }\n\n        // Make a variable to store the Answer.\n        double ans = 0;\n\n        // Now loop over the classes array and calculate the sum of the pass ratios of the classes.\n        for (int i = 0; i < n; i++)\n            ans += divide(classes[i][0], classes[i][1]);\n\n        // Now return the Average pass ratio.\n        return ans / (double) n;\n    }\n\n    // This Method First casts the int into double then returns there division as double.\n    double divide(int first, int sec) {\n        return (double) first / (double) sec;\n    }\n\n    // This method Updates the Classes Array \n    // And also returns the Updated Pair.\n    Pair update(int[][] classes, Pair pair) {\n        int idx = pair.idx;\n\n        classes[idx][0]++;\n        classes[idx][1]++;\n\n        double change = divide(classes[idx][0] +1, classes[idx][1] +1)\n                            - divide(classes[idx][0], classes[idx][1]);\n\n        return new Pair(change, idx);\n    }\n}\n\n// This is the implementation of Pair Class\nclass Pair implements Comparable<Pair> {\n    double change;\n    int idx;\n\n    Pair(double change, int idx){\n        this.change = change;\n        this.idx = idx;\n    }\n\n    // I have added this so the PriorityQueue will save the Pair in the order according to me.\n    @Override\n    public int compareTo(Pair other){\n        if(this.change == other.change) return 0;\n\n        return this.change > other.change ? -1 : 1;\n    }\n}\n```
['Greedy', 'Heap (Priority Queue)', 'Java']