Kth Smallest Number in Multiplication Table
Last Updated :
23 Mar, 2024
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))
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 > 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))
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 < h:
mid = (l+h)//2
if count(m, n, mid) < 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))
Time Complexity: O(M * log(M*N))
Auxiliary Space: O(1)
Share your thoughts in the comments
Please Login to comment...