Indexes of Top K

Last Updated : 21 Jun, 2026

Given an array arr[] representing the marks of students and an integer k, return the indices (0-based) of students having the top k distinct marks. The indices should be ordered by marks in descending order, and for students with the same marks, their indices should appear in ascending order.

Examples:

Input: arr = [2, 2, 1, 3, 1], k = 3
Output: [3, 0, 1, 2, 4]
Explanation: Topper with 3 marks is present at 3rd index, 2 marks is present at 0th index and next at 1st index. 1 marks is present at 2 and 4.

Input: arr = [1, 2, 3, 4], k = 1
Output: [3]
Explanation: The highest marks is at index 3.

Try It Yourself
redirect icon

[Naive Approach] Repeatedly Finding the Next Maximum Marks - O(n × k) Time and O(1) Space

To find the top k distinct marks, repeatedly scan the array to find the largest mark that is smaller than the previously selected mark. For each selected mark, traverse the array again and collect the indices of all students having that mark. Since the array may be scanned multiple times for each of the k distinct marks, the overall time complexity becomes O(n × k).

C++
#include <bits/stdc++.h>
using namespace std;

vector<int> topKIndices(vector<int> &arr, int k) {
    vector<int> ans;
    int prevMax = INT_MAX;

    while (k--) {
        int currMax = INT_MIN;

        // Find the next maximum distinct mark.
        for (int x : arr) {
            if (x < prevMax) {
                currMax = max(currMax, x);
            }
        }

        // Collect indices having this mark.
        for (int i = 0; i < arr.size(); i++) {
            if (arr[i] == currMax) {
                ans.push_back(i);
            }
        }

        prevMax = currMax;
    }

    return ans;
}

int main() {
    vector<int> arr = {2, 2, 1, 3, 1};
    int k = 3;

    vector<int> ans = topKIndices(arr, k);

    for (int x : ans) {
        cout << x << " ";
    }

    return 0;
}
Java
import java.util.ArrayList;

class GFG {

    static ArrayList<Integer> topKIndices(int[] arr, int k) {
        ArrayList<Integer> ans = new ArrayList<>();
        int prevMax = Integer.MAX_VALUE;

        while (k-- > 0) {
            int currMax = Integer.MIN_VALUE;

            // Find the next maximum distinct mark.
            for (int x : arr) {
                if (x < prevMax) {
                    currMax = Math.max(currMax, x);
                }
            }

            // Collect indices having this mark.
            for (int i = 0; i < arr.length; i++) {
                if (arr[i] == currMax) {
                    ans.add(i);
                }
            }

            prevMax = currMax;
        }

        return ans;
    }

    public static void main(String[] args) {
        int[] arr = {2, 2, 1, 3, 1};
        int k = 3;

        System.out.println(topKIndices(arr, k));
    }
}
Python
def topKIndices(arr, k):
    ans = []
    prev_max = float('inf')

    while k > 0:
        curr_max = float('-inf')

        # Find the next maximum distinct mark.
        for x in arr:
            if x < prev_max:
                curr_max = max(curr_max, x)

        # Collect indices having this mark.
        for i in range(len(arr)):
            if arr[i] == curr_max:
                ans.append(i)

        prev_max = curr_max
        k -= 1

    return ans


arr = [2, 2, 1, 3, 1]
k = 3

print(topKIndices(arr, k))
C#
using System;
using System.Collections.Generic;

class GFG
{
    static List<int> topKIndices(int[] arr, int k)
    {
        List<int> ans = new List<int>();
        int prevMax = int.MaxValue;

        while (k-- > 0)
        {
            int currMax = int.MinValue;

            // Find the next maximum distinct mark.
            foreach (int x in arr)
            {
                if (x < prevMax)
                {
                    currMax = Math.Max(currMax, x);
                }
            }

            // Collect indices having this mark.
            for (int i = 0; i < arr.Length; i++)
            {
                if (arr[i] == currMax)
                {
                    ans.Add(i);
                }
            }

            prevMax = currMax;
        }

        return ans;
    }

    static void Main()
    {
        int[] arr = { 2, 2, 1, 3, 1 };
        int k = 3;

        List<int> ans = topKIndices(arr, k);

        foreach (int x in ans)
        {
            Console.Write(x + " ");
        }
    }
}
JavaScript
function topKIndices(arr, k) {
    const ans = [];
    let prevMax = Number.MAX_SAFE_INTEGER;

    while (k--) {
        let currMax = Number.MIN_SAFE_INTEGER;

        // Find the next maximum distinct mark.
        for (const x of arr) {
            if (x < prevMax) {
                currMax = Math.max(currMax, x);
            }
        }

        // Collect indices having this mark.
        for (let i = 0; i < arr.length; i++) {
            if (arr[i] === currMax) {
                ans.push(i);
            }
        }

        prevMax = currMax;
    }

    return ans;
}

// Driver Code
const arr = [2, 2, 1, 3, 1];
const k = 3;

console.log(topKIndices(arr, k));

Output
3 0 1 2 4 

[Better Approach] Sorting Marks with Indices - O(n log n) Time and O(n) Space

Store each student's marks along with their index and sort them in descending order of marks. For students with the same marks, sort by index in ascending order. After sorting, the students belonging to the top k distinct marks appear consecutively. Traverse the sorted array, count distinct marks encountered so far, and collect the corresponding indices until k distinct marks have been processed.

C++
#include <bits/stdc++.h>
using namespace std;

vector<int> topKIndices(vector<int> &arr, int k) {
    vector<pair<int, int>> marksIndices;

    for (int i = 0; i < arr.size(); i++) {
        marksIndices.push_back({arr[i], i});
    }

    // Sort by marks descending and index ascending.
    sort(marksIndices.begin(), marksIndices.end(),
         [](pair<int, int> &a, pair<int, int> &b) {
             if (a.first != b.first) {
                 return a.first > b.first;
             }
             return a.second < b.second;
         });

    vector<int> ans;
    int distinct = 0;

    for (int i = 0; i < marksIndices.size(); i++) {
        if (i == 0 || marksIndices[i].first != marksIndices[i - 1].first) {
            distinct++;
        }

        if (distinct > k) {
            break;
        }

        ans.push_back(marksIndices[i].second);
    }

    return ans;
}

int main() {
    vector<int> arr = {2, 2, 1, 3, 1};
    int k = 3;

    vector<int> ans = topKIndices(arr, k);

    for (int x : ans) {
        cout << x << " ";
    }

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Collections;

class GFG {

    static ArrayList<Integer> topKIndices(int[] arr, int k) {
        ArrayList<int[]> marksIndices = new ArrayList<>();

        for (int i = 0; i < arr.length; i++) {
            marksIndices.add(new int[]{arr[i], i});
        }

        // Sort by marks descending and index ascending.
        Collections.sort(marksIndices, (a, b) -> {
            if (a[0] != b[0]) {
                return b[0] - a[0];
            }
            return a[1] - b[1];
        });

        ArrayList<Integer> ans = new ArrayList<>();
        int distinct = 0;

        for (int i = 0; i < marksIndices.size(); i++) {
            if (i == 0 ||
                marksIndices.get(i)[0] != marksIndices.get(i - 1)[0]) {
                distinct++;
            }

            if (distinct > k) {
                break;
            }

            ans.add(marksIndices.get(i)[1]);
        }

        return ans;
    }

    public static void main(String[] args) {
        int[] arr = {2, 2, 1, 3, 1};
        int k = 3;

        System.out.println(topKIndices(arr, k));
    }
}
Python
def topKIndices(arr, k):
    marks_indices = []

    for i in range(len(arr)):
        marks_indices.append((arr[i], i))

    # Sort by marks descending and index ascending.
    marks_indices.sort(key=lambda x: (-x[0], x[1]))

    ans = []
    distinct = 0

    for i in range(len(marks_indices)):
        if i == 0 or marks_indices[i][0] != marks_indices[i - 1][0]:
            distinct += 1

        if distinct > k:
            break

        ans.append(marks_indices[i][1])

    return ans


arr = [2, 2, 1, 3, 1]
k = 3

print(topKIndices(arr, k))
C#
using System;
using System.Collections.Generic;

class GFG
{
    static List<int> topKIndices(int[] arr, int k)
    {
        List<(int marks, int index)> marksIndices =
            new List<(int marks, int index)>();

        for (int i = 0; i < arr.Length; i++)
        {
            marksIndices.Add((arr[i], i));
        }

        // Sort by marks descending and index ascending.
        marksIndices.Sort((a, b) =>
        {
            if (a.marks != b.marks)
            {
                return b.marks.CompareTo(a.marks);
            }

            return a.index.CompareTo(b.index);
        });

        List<int> ans = new List<int>();
        int distinct = 0;

        for (int i = 0; i < marksIndices.Count; i++)
        {
            if (i == 0 ||
                marksIndices[i].marks != marksIndices[i - 1].marks)
            {
                distinct++;
            }

            if (distinct > k)
            {
                break;
            }

            ans.Add(marksIndices[i].index);
        }

        return ans;
    }

    static void Main()
    {
        int[] arr = { 2, 2, 1, 3, 1 };
        int k = 3;

        List<int> ans = topKIndices(arr, k);

        foreach (int x in ans)
        {
            Console.Write(x + " ");
        }
    }
}
JavaScript
function topKIndices(arr, k) {
    const marksIndices = [];

    for (let i = 0; i < arr.length; i++) {
        marksIndices.push([arr[i], i]);
    }

    // Sort by marks descending and index ascending.
    marksIndices.sort((a, b) => {
        if (a[0] !== b[0]) {
            return b[0] - a[0];
        }

        return a[1] - b[1];
    });

    const ans = [];
    let distinct = 0;

    for (let i = 0; i < marksIndices.length; i++) {
        if (i === 0 ||
            marksIndices[i][0] !== marksIndices[i - 1][0]) {
            distinct++;
        }

        if (distinct > k) {
            break;
        }

        ans.push(marksIndices[i][1]);
    }

    return ans;
}

// Driver Code
const arr = [2, 2, 1, 3, 1];
const k = 3;

console.log(topKIndices(arr, k));

Output
3 0 1 2 4 

[Expected Approach] Using Min Heap and Hash Map

Instead of sorting all distinct marks, maintain a min heap of size k to keep track of the k largest distinct marks seen so far. First, group the indices corresponding to each mark using a hash map. Then, process the distinct marks and maintain the top k marks in the min heap. Finally, retrieve these marks in descending order and append their stored indices to the answer.

Step By Step Implementation:

  • Create a hash map where: Key = marks, Value = list of indices having those marks.
  • Traverse the distinct marks and maintain a min heap of size k containing the top k marks.
  • Extract all marks from the heap and sort them in descending order.
  • For each selected mark, append its stored indices to the answer.
C++
#include <iostream>
#include <unordered_map>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

vector<int> topKIndices(vector<int> &arr, int k) {

    // Group indices having the same marks.
    unordered_map<int, vector<int>> mp;

    for (int i = 0; i < arr.size(); i++) {
        mp[arr[i]].push_back(i);
    }

    // Min heap storing the top k distinct marks.
    priority_queue<int, vector<int>, greater<int>> pq;

    for (auto &[mark, indices] : mp) {

        if (pq.size() < k) {
            pq.push(mark);
        }
        else if (mark > pq.top()) {
            pq.pop();
            pq.push(mark);
        }
    }

    vector<int> topMarks;

    while (!pq.empty()) {
        topMarks.push_back(pq.top());
        pq.pop();
    }

    // Process selected marks in descending order.
    sort(topMarks.rbegin(), topMarks.rend());

    vector<int> ans;

    for (int mark : topMarks) {
        for (int idx : mp[mark]) {
            ans.push_back(idx);
        }
    }

    return ans;
}

int main() {
    vector<int> arr = {2, 2, 1, 3, 1};
    int k = 3;

    vector<int> ans = topKIndices(arr, k);

    for (int x : ans) {
        cout << x << " ";
    }

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.PriorityQueue;

class GFG {

    static ArrayList<Integer> topKIndices(int[] arr, int k) {

        // Group indices having the same marks.
        HashMap<Integer, ArrayList<Integer>> map = new HashMap<>();

        for (int i = 0; i < arr.length; i++) {
            map.putIfAbsent(arr[i], new ArrayList<>());
            map.get(arr[i]).add(i);
        }

        // Min heap storing the top k distinct marks.
        PriorityQueue<Integer> pq = new PriorityQueue<>();

        for (int mark : map.keySet()) {

            if (pq.size() < k) {
                pq.offer(mark);
            }
            else if (mark > pq.peek()) {
                pq.poll();
                pq.offer(mark);
            }
        }

        ArrayList<Integer> topMarks = new ArrayList<>();

        while (!pq.isEmpty()) {
            topMarks.add(pq.poll());
        }

        // Process selected marks in descending order.
        Collections.sort(topMarks, Collections.reverseOrder());

        ArrayList<Integer> ans = new ArrayList<>();

        for (int mark : topMarks) {
            ans.addAll(map.get(mark));
        }

        return ans;
    }

    public static void main(String[] args) {
        int[] arr = {2, 2, 1, 3, 1};
        int k = 3;

        System.out.println(topKIndices(arr, k));
    }
}
Python
from heapq import heappush, heapreplace, heappop

def topKIndices(arr, k):

    # Group indices having the same marks.
    mp = {}

    for i, mark in enumerate(arr):
        if mark not in mp:
            mp[mark] = []
        mp[mark].append(i)

    # Min heap storing the top k distinct marks.
    pq = []

    for mark in mp:

        if len(pq) < k:
            heappush(pq, mark)
        elif mark > pq[0]:
            heapreplace(pq, mark)

    top_marks = []

    while pq:
        top_marks.append(heappop(pq))

    # Process selected marks in descending order.
    top_marks.sort(reverse=True)

    ans = []

    for mark in top_marks:
        ans.extend(mp[mark])

    return ans


arr = [2, 2, 1, 3, 1]
k = 3

print(topKIndices(arr, k))
C#
using System;
using System.Collections.Generic;

class GFG
{
    static List<int> topKIndices(int[] arr, int k)
    {
        // Group indices having the same marks.
        Dictionary<int, List<int>> map =
            new Dictionary<int, List<int>>();

        for (int i = 0; i < arr.Length; i++)
        {
            if (!map.ContainsKey(arr[i]))
            {
                map[arr[i]] = new List<int>();
            }

            map[arr[i]].Add(i);
        }

        // Min heap storing the top k distinct marks.
        PriorityQueue<int, int> pq =
            new PriorityQueue<int, int>();

        foreach (int mark in map.Keys)
        {
            if (pq.Count < k)
            {
                pq.Enqueue(mark, mark);
            }
            else if (mark > pq.Peek())
            {
                pq.Dequeue();
                pq.Enqueue(mark, mark);
            }
        }

        List<int> topMarks = new List<int>();

        while (pq.Count > 0)
        {
            topMarks.Add(pq.Dequeue());
        }

        // Process selected marks in descending order.
        topMarks.Sort((a, b) => b.CompareTo(a));

        List<int> ans = new List<int>();

        foreach (int mark in topMarks)
        {
            ans.AddRange(map[mark]);
        }

        return ans;
    }

    static void Main()
    {
        int[] arr = { 2, 2, 1, 3, 1 };
        int k = 3;

        List<int> ans = topKIndices(arr, k);

        foreach (int x in ans)
        {
            Console.Write(x + " ");
        }
    }
}
JavaScript
function topKIndices(arr, k) {

    // Group indices having the same marks.
    const mp = new Map();

    for (let i = 0; i < arr.length; i++) {
        if (!mp.has(arr[i])) {
            mp.set(arr[i], []);
        }

        mp.get(arr[i]).push(i);
    }

    // Min heap storing the top k distinct marks.
    const topMarks = [...mp.keys()]
        .sort((a, b) => b - a)
        .slice(0, k);

    const ans = [];

    for (const mark of topMarks) {
        ans.push(...mp.get(mark));
    }

    return ans;
}

const arr = [2, 2, 1, 3, 1];
const k = 3;

console.log(topKIndices(arr, k));

Output
3 0 1 2 4 

Time Complexity: O(n log k) - Building the map takes O(n), and maintaining a min heap of size k for n marks takes O(n log k).
Auxiliary Space: O(n) - Storing the indices corresponding to each mark in the hash map takes O(n).

Comment