Open In App

Kth Smallest Number in Multiplication Table

Last Updated : 23 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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: 6 
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:

  • Define an empty array of size M*N
  • Run the outer loop from 1 to M i.e. 1 <= i <= m
  • Run the inner loop from 1 to N i.e. 1 <= j <= n
  • Append the element (i*j) in the array
  • When the nested loops ends sort the array in ascending order
  • Print or return the element present at K-1 index of the array

Below is the implementation of the above approach:

C++
#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;
}
Java
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);
    }
}
C#
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
// 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
Python3
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:

  • Import the heap module/library based on you programming language.
  • Define a empty heap of size K, lets name the heap as pq
  • Run two nested loop, one from 1 to M i.e. 1 <= i <= m and another from 1 to N i.e. 1 <= j <= n
  • The element (val) will be the product of i,j (i.e. val = i*j)
  • If the length of heap is equal to K then check for another condition that (val > peek element of heap) if its true then pop the peek element from heap and push the new element (i*j) into the heap, else continue
  • If length of the heap is less than K then push the element (i*j) into the heap
  • When the nested loops ends return or print the peek element of heap as it is our answer

Below is the implementation of the above:

C++
#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;
}
Java
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));
    }
}
C#
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));
    }
}
Javascript
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));
Python3
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:

  • Initialize the low = 1 and high = m*n
  • Run a while loop with condition (low<high)
  • Define a interger mid as mid = (low+high)/2
  • To make code more readable make a function name count with paramerters (m,n,val)
  • In the count function initialize a cnt variable
  • Run a loop from 1 to m+1 i.e. 1 <= i <= m
  • Increment the cnt variable as cnt = cnt + min(val/i,n)
  • When the loop ends return the cnt variable
  • In the step 3 we defined the mid variable, pass the mid in the count variable along with other variable count(m,n,mid)
  • If the count(m, n, mid) < K then set the low as mid+1 i.e. low = mid+1 else set the high as mid i.e. high=mid
  • When the loop ends return or print the low since it’s our answer

Below is the implementation of the above:

C++
#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
Java
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.
C#
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));
    }
}
Javascript
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));
Python3
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)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads