Open In App

Kth Smallest Number in Multiplication Table

Given three integers M, N, and K. Consider a grid of M * N, where mat[i][j] = i*j (1 based index). The task is to return the Kth smallest element in the M*N multiplication table.

Examples:

Input: M = 3, N = 3, K = 5
Output: 3
Explanation:

The 5th smallest element is 3. 

Input: M = 2, N = 3, K = 6
Output:
Explanation: [1, 2, 3][2, 4, 6]. The 6th smallest element is 6.

Naive Approach: The basic way to solve the problem is as follows:

Steps to solve the problem:

Below is the implementation of the above approach:

#include <iostream>
#include <vector>
#include <algorithm>

class Solution {
public:
    // Function to find the kth smallest number in the
    // multiplication table
    int findKthNumber(int m, int n, int k) {
        std::vector<int> res;

        // Generate all possible products and store them in
        // the vector
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                res.push_back(i * j);
            }
        }

        // Sort the vector of products
        std::sort(res.begin(), res.end());

        // Return the kth smallest number
        return res[k - 1];
    }
};

int main() {
    int m = 3, n = 3, k = 5;
    Solution solution;

    // Call the function and print the result
    int result = solution.findKthNumber(m, n, k);
    std::cout << result << std::endl;

    return 0;
}
import java.util.*;

public class Solution {
    // Function to find the kth smallest number in the
    // multiplication table
    public int findKthNumber(int m, int n, int k)
    {
        List<Integer> res = new ArrayList<>();

        // Generate all possible products and store them in
        // the list
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                res.add(i * j);
            }
        }

        // Sort the list of products
        Collections.sort(res);

        // Return the kth smallest number
        return res.get(k - 1);
    }

    // Main method for testing the function
    public static void main(String[] args)
    {
        // Example input
        int m = 3, n = 3, k = 5;
        Solution solution = new Solution();

        // Call the function and print the result
        int result = solution.findKthNumber(m, n, k);
        System.out.println(result);
    }
}
using System;
using System.Collections.Generic;
using System.Linq;

class Solution
{
    // Function to find the kth smallest number in the
    // multiplication table
    public int FindKthNumber(int m, int n, int k)
    {
        List<int> res = new List<int>();

        // Generate all possible products and store them in
        // the list
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                res.Add(i * j);
            }
        }

        // Sort the list of products
        res.Sort();

        // Return the kth smallest number
        return res[k - 1];
    }
}

class Program
{
    static void Main()
    {
        int m = 3, n = 3, k = 5;
        Solution solution = new Solution();

        // Call the function and print the result
        int result = solution.FindKthNumber(m, n, k);
        Console.WriteLine(result);
    }
}
// Javascript code for the above approach

function findKthNumber(m, n, k) {
    res = []
    for (let i = 1; i < m + 1; i++) {
        for (let j = 1; j < n + 1; j++) {
            res.push(i * j)
        }
    }
    res.sort()
    return res[k - 1]
}


// Driver Code
let m = 3, n = 3
let k = 5
console.log(findKthNumber(m, n, k))

// This code is contributed by ragul21
class Solution:
    def findKthNumber(self, m, n, k):
        res = []
        for i in range(1, m+1):
            for j in range(1, n+1):
                res.append(i*j)
        res.sort()
        return res[k-1]


# Driver Code
m, n = 3, 3
k = 5
res = Solution()
print(res.findKthNumber(m, n, k))

Output
3









Time Complexity: O(M*N*log(M*N))
Auxiliary Space: O(M*N)

Optimized Approach: Min Heap Approach

Steps to solve the problem:

Below is the implementation of the above:

#include <iostream>
#include <vector>
#include <queue>

class Solution {
public:
    int findKthNumber(int m, int n, int k) {
        std::priority_queue<int, std::vector<int>, std::greater<int>> pq;  // Use min heap
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                int val = i * j;
                if (pq.size() == k) {
                    if (val > pq.top()) {
                        pq.pop();
                        pq.push(val);
                    } else {
                        continue;
                    }
                } else {
                    pq.push(val);
                }
            }
        }
        return pq.top();
    }
};

// Driver Code
int main() {
    int m = 3, n = 3, k = 5;
    Solution res;
    std::cout << res.findKthNumber(m, n, k) << std::endl;
    return 0;
}
import java.util.PriorityQueue;

class Solution {
    public int findKthNumber(int m, int n, int k) {
        // Use min heap to keep track of the smallest values
        PriorityQueue<Integer> pq = new PriorityQueue<>();

        // Iterate over all possible combinations of i and j
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                int val = i * j;

                // Check if the min heap is already of size k
                if (pq.size() == k) {
                    // If the current value is greater than the smallest value in the heap,
                    // replace the smallest value with the current value
                    if (val > pq.peek()) {
                        pq.poll();
                        pq.offer(val);
                    } else {
                        continue;
                    }
                } else {
                    // If the heap is not of size k yet, simply push the current value
                    pq.offer(val);
                }
            }
        }

        // The top of the min heap now contains the kth smallest element
        return pq.peek();
    }

    // Driver Code
    public static void main(String[] args) {
        // Test case values
        int m = 3, n = 3, k = 5;
        Solution solution = new Solution();

        // Find and print the kth smallest element
        System.out.println(solution.findKthNumber(m, n, k));
    }
}
using System;
using System.Collections.Generic;

// Main class for the solution
public class Solution
{
    // Method to find the kth smallest element in the matrix
    public int FindKthNumber(int m, int n, int k)
    {
        // Use min heap to keep track of the k smallest elements
        var pq = new PriorityQueue<int>();

        // Iterate over each element in the matrix
        for (int i = 1; i <= m; ++i)
        {
            for (int j = 1; j <= n; ++j)
            {
                int val = i * j;

                // Check if the heap has already k elements
                if (pq.Count == k)
                {
                    // If the current value is greater than the smallest element in the heap,
                    // replace the smallest element with the current value
                    if (val > pq.Peek())
                    {
                        pq.Dequeue();
                        pq.Enqueue(val);
                    }
                    else
                    {
                        // If the current value is not greater, move to the next iteration
                        continue;
                    }
                }
                else
                {
                    // If the heap has less than k elements, add the current value to the heap
                    pq.Enqueue(val);
                }
            }
        }

        // Return the smallest element in the heap, which is the kth smallest element in the matrix
        return pq.Peek();
    }
}

// Priority Queue implementation
public class PriorityQueue<T> where T : IComparable<T>
{
    private List<T> heap = new List<T>();

    public int Count => heap.Count;

    // Enqueue operation to add an element to the heap
    public void Enqueue(T item)
    {
        heap.Add(item);
        int i = Count - 1;

        // Maintain the heap property by swapping elements
        while (i > 0)
        {
            int parent = (i - 1) / 2;

            if (heap[i].CompareTo(heap[parent]) >= 0)
            {
                break;
            }

            Swap(i, parent);
            i = parent;
        }
    }

    // Dequeue operation to remove the smallest element from the heap
    public T Dequeue()
    {
        if (Count == 0)
        {
            throw new InvalidOperationException("PriorityQueue is empty");
        }

        T root = heap[0];
        heap[0] = heap[Count - 1];
        heap.RemoveAt(Count - 1);

        int i = 0;

        // Maintain the heap property by swapping elements
        while (true)
        {
            int leftChild = 2 * i + 1;
            int rightChild = 2 * i + 2;

            if (leftChild >= Count)
            {
                break;
            }

            int minChild = leftChild;

            if (rightChild < Count && heap[rightChild].CompareTo(heap[leftChild]) < 0)
            {
                minChild = rightChild;
            }

            if (heap[i].CompareTo(heap[minChild]) <= 0)
            {
                break;
            }

            Swap(i, minChild);
            i = minChild;
        }

        return root;
    }

    // Peek operation to get the smallest element in the heap without removing it
    public T Peek()
    {
        if (Count == 0)
        {
            throw new InvalidOperationException("PriorityQueue is empty");
        }

        return heap[0];
    }

    // Helper method to swap elements in the heap
    private void Swap(int i, int j)
    {
        T temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
}

// Driver Code
class Program
{
    static void Main()
    {
        // Example input values
        int m = 3, n = 3, k = 5;

        // Create an instance of the Solution class
        Solution res = new Solution();

        // Call the FindKthNumber method and print the result
        Console.WriteLine(res.FindKthNumber(m, n, k));
    }
}
class Solution {
    findKthNumber(m, n, k) {
        const pq = []; // Use min heap (implemented with array)
        for (let i = 1; i <= m; ++i) {
            for (let j = 1; j <= n; ++j) {
                const val = i * j;
                if (pq.length === k) {
                    if (val > pq[0]) { // Compare with the top element of the heap
                        pq.shift(); // Remove the smallest element
                        pq.push(val); // Insert the new value
                        pq.sort((a, b) => a - b); // Re-sort the array
                    } else {
                        continue;
                    }
                } else {
                    pq.push(val); // Insert the new value
                    pq.sort((a, b) => a - b); // Re-sort the array
                }
            }
        }
        return pq[0]; // Return the top element of the heap
    }
}

// Driver Code
const m = 3, n = 3, k = 5;
const res = new Solution();
console.log(res.findKthNumber(m, n, k));
import heapq


class Solution:
    def findKthNumber(self, m, n, k):
        pq = []
        for i in range(1, m+1):
            for j in range(1, n+1):
                val = i*j
                if len(pq) == k:
                    if val*-1 &gt; pq[0]:
                        heapq.heappop(pq)
                        heapq.heappush(pq, val*-1)
                    else:
                        continue
                else:
                    heapq.heappush(pq, val*-1)
        return pq[0]*-1


# Driver Code
m, n = 3, 3
k = 5
res = Solution()
print(res.findKthNumber(m, n, k))

Output
3









Time Complexity: O(M*N*log(K))
Auxiliary Space: O(K)

Efficient Approach: Using Binary Search (Optimized Approach)

We have covered a detailed video of the problem at GFG with detailed illustratives along with examples which helps you to gain better understanding of approach which you can check here.

Steps to solve the problem:

Below is the implementation of the above:

#include <iostream>
using namespace std;

class Solution {
public:
    // Function to find the kth number
    int findKthNumber(int m, int n, int k) {
        // Function to count numbers less than or equal to val
        auto count = [&](int val) {
            int cnt = 0;
            for (int i = 1; i <= m; ++i) {
                cnt += min(val / i, n);
            }
            return cnt;
        };

        // Binary search to find the kth number
        int l = 1, h = m * n;
        while (l < h) {
            int mid = (l + h) / 2;
            if (count(mid) < k) {
                l = mid + 1;
            } else {
                h = mid;
            }
        }
        return l; // Return the kth number
    }
};

int main() {
    int m = 3, n = 3, k = 5;
    Solution res;
    // Printing the result
    cout << "Kth Number: " << res.findKthNumber(m, n, k);
    return 0;
}
//This code is contributed by Adarsh
public class Solution {

    // Function to find the kth number
    public int findKthNumber(int m, int n, int k) {
        // Function to count numbers less than or equal to val

        // Binary search to find the kth number
        int l = 1, h = m * n;
        while (l < h) {
            int mid = (l + h) / 2;
            if (count(mid, m, n) < k) {
                l = mid + 1;
            } else {
                h = mid;
            }
        }
        return l; // Return the kth number
    }

    // Function to count numbers less than or equal to val
    private int count(int val, int m, int n) {
        int cnt = 0;
        for (int i = 1; i <= m; ++i) {
            cnt += Math.min(val / i, n);
        }
        return cnt;
    }

    public static void main(String[] args) {
        int m = 3, n = 3, k = 5;
        Solution res = new Solution();
        // Printing the result
        System.out.println("Kth Number: " + res.findKthNumber(m, n, k));
    }
}
//This code is contributed by Utkarsh.
using System;

public class Solution
{
    // Function to find the kth number
    public int FindKthNumber(int m, int n, int k)
    {
        // Function to count numbers less than or equal to val
        Func<int, int> count = (int val) =>
        {
            int cnt = 0;
            for (int i = 1; i <= m; ++i)
            {
                cnt += Math.Min(val / i, n);
            }
            return cnt;
        };

        // Binary search to find the kth number
        int l = 1, h = m * n;
        while (l < h)
        {
            int mid = (l + h) / 2;
            if (count(mid) < k)
            {
                l = mid + 1;
            }
            else
            {
                h = mid;
            }
        }
        return l; // Return the kth number
    }
}

class Program
{
    static void Main()
    {
        int m = 3, n = 3, k = 5;
        Solution solution = new Solution();
        
        // Printing the result
        Console.WriteLine("Kth Number: " + solution.FindKthNumber(m, n, k));
    }
}
class Solution {
    findKthNumber(m, n, k) {
        function count(m, n, val) {
            let cnt = 0;
            for (let i = 1; i <= m; i++) {
                cnt += Math.min(Math.floor(val / i), n);
            }
            return cnt;
        }

        let l = 1, h = m * n;
        while (l < h) {
            let mid = Math.floor((l + h) / 2);
            if (count(m, n, mid) < k) {
                l = mid + 1;
            } else {
                h = mid;
            }
        }
        return l;
    }
}

// Driver Code
let m = 3, n = 3, k = 5;
let res = new Solution();
console.log(res.findKthNumber(m, n, k));
class Solution:
    def findKthNumber(self, m, n, k):
        def count(m, n, val):
            cnt = 0
            for i in range(1, m+1):
                cnt += min(val//i, n)
            return cnt

        l, h = 1, m*n
        while l &lt; h:
            mid = (l+h)//2
            if count(m, n, mid) &lt; k:
                l = mid+1
            else:
                h = mid
        return l


# Driver Code
m, n = 3, 3
k = 5
res = Solution()
print(res.findKthNumber(m, n, k))

Output
3



















Time Complexity: O(M * log(M*N))
Auxiliary Space: O(1)

Article Tags :