Most Frequent Prime solution and explanation
6 more videos on this problem
Most Frequent Prime | Leetcode 3044Ayushi Sharma · 16:07 · 796 views
3044 Most Frequent Prime || Sieve + Recursion ✅Ayush Rao · 7:53 · 395 views
Leetcode 3044. Most Frequent Prime TLE? HindiThinkCode · 9:59 · 304 views
3044. Most Frequent Prime (Leetcode Medium)Programming Live with Larry · 14:19 · 291 views
3044. Most Frequent Prime | Weekly Contest 385 | Easy Explanation | LeetcodeRapid Syntax · 13:31 · 110 views
LeetCode 3044 - Most Frequent Prime - PythonAlpha-Code · 15:36 · 40 views
Leetcode 3044 Most Frequent PrimeAlgorithmicIQ · 19:08 · 8 views
The problem
You are given a m x n 0-indexed 2D matrix mat. From every cell, you can create numbers in the following way:
- There could be at most
8paths from the cells namely: east, south-east, south, south-west, west, north-west, north, and north-east. - Select a path from them and append digits in this path to the number being formed by traveling in this direction.
- Note that numbers are generated at every step, for example, if the digits along the path are
1, 9, 1, then there will be three numbers generated along the way:1, 19, 191.
Return the most frequent prime number greater than 10 out of all the numbers created by traversing the matrix or -1 if no such prime number exists. If there are multiple prime numbers with the highest frequency, then return the largest among them.
Note: It is invalid to change the direction during the move.
Example 1:
Input: mat = [[1,1],[9,9],[1,1]] Output: 19 Explanation: From cell (0,0) there are 3 possible directions and the numbers greater than 10 which can be created in those directions are: East: [11], South-East: [19], South: [19,191]. Numbers greater than 10 created from the cell (0,1) in all possible directions are: [19,191,19,11]. Numbers greater than 10 created from the cell (1,0) in all possible directions are: [99,91,91,91,91]. Numbers greater than 10 created from the cell (1,1) in all possible directions are: [91,91,99,91,91]. Numbers greater than 10 created from the cell (2,0) in all possible directions are: [11,19,191,19]. Numbers greater than 10 created from the cell (2,1) in all possible directions are: [11,19,19,191]. The most frequent prime number among all the created numbers is 19.
Example 2:
Input: mat = [[7]] Output: -1 Explanation: The only number which can be formed is 7. It is a prime number however it is not greater than 10, so return -1.
Example 3:
Input: mat = [[9,7,8],[4,6,5],[2,8,6]] Output: 97 Explanation: Numbers greater than 10 created from the cell (0,0) in all possible directions are: [97,978,96,966,94,942]. Numbers greater than 10 created from the cell (0,1) in all possible directions are: [78,75,76,768,74,79]. Numbers greater than 10 created from the cell (0,2) in all possible directions are: [85,856,86,862,87,879]. Numbers greater than 10 created from the cell (1,0) in all possible directions are: [46,465,48,42,49,47]. Numbers greater than 10 created from the cell (1,1) in all possible directions are: [65,66,68,62,64,69,67,68]. Numbers greater than 10 created from the cell (1,2) in all possible directions are: [56,58,56,564,57,58]. Numbers greater than 10 created from the cell (2,0) in all possible directions are: [28,286,24,249,26,268]. Numbers greater than 10 created from the cell (2,1) in all possible directions are: [86,82,84,86,867,85]. Numbers greater than 10 created from the cell (2,2) in all possible directions are: [68,682,66,669,65,658]. The most frequent prime number among all the created numbers is 97.
Constraints:
m == mat.lengthn == mat[i].length1 <= m, n <= 61 <= mat[i][j] <= 9
Approach overview
Problem Overview: You are given a matrix of digits. Starting from any cell, build numbers by moving through the grid and concatenating digits along the path. Every number formed is checked for primality, and the task is to return the prime that appears most frequently. If multiple primes have the same frequency, return the largest one.
Approach 1: Depth First Search (DFS) with Path Tracking (O(m * n * k), Space: O(P))
This approach treats the grid like a search space and explores number formations using DFS. From each cell, move in all eight possible directions and keep appending digits to build numbers step by step. Each time a new number is formed, run a primality test and update its frequency in a hash map. The key insight is incremental number construction: instead of recomputing digits each time, multiply the current value by 10 and append the next digit. DFS naturally handles path exploration and ensures all directional sequences are checked. Time complexity is O(m * n * k) where k is the maximum path length, and space complexity is O(P) for storing counts of discovered primes.
This method works well because matrix traversal and incremental number building are efficient. A hash map from the Hash Table category keeps track of prime frequencies. Primality checking relies on basic Number Theory techniques such as checking divisibility up to the square root.
Approach 2: Backtracking Focused on Matrix Paths (O(m * n * k), Space: O(P + k))
Backtracking explores digit sequences similarly but focuses explicitly on matrix paths. Start from each cell and recursively extend the current number while moving in a fixed direction. Each recursive step appends a digit, evaluates whether the new value is prime, and records it in a frequency map. Because the path continues until it exits the grid boundary, recursion depth stays bounded by the grid dimension. Backtracking makes the state transition clear: current position, current number, and chosen direction.
This approach is easier to reason about when modeling the grid as a path-building problem from the Matrix traversal family. The algorithm maintains a global counter for primes and updates the most frequent candidate during traversal. Time complexity remains O(m * n * k) and space complexity is O(P + k), where k represents recursion depth.
Recommended for interviews: The DFS enumeration approach is typically expected. Interviewers want to see that you recognize the grid traversal pattern, generate numbers incrementally, and store frequencies using a hash map. Demonstrating brute enumeration of paths shows problem understanding, but combining traversal with efficient prime checking and counting shows stronger algorithmic skill.
Approach 1: Depth First Search (DFS) with Path Tracking
This approach uses Depth First Search to explore all paths from each cell in the matrix. For each path, we generate numbers by appending digits step-by-step. Then, we check if these numbers are prime and track their frequencies. Finally, we determine the most frequent prime number greater than 10.
from collections import defaultdict
DIRECTIONS = [(0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1)]
def is_prime(n):
if n <= 1:
return False
if n <= 3:
return n > 1
if n % 2 == 0 or n % 3 == 0:
return False
i = 5
while i * i <= n:
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return n > 10
def dfs(mat, m, n, x, y, number, visited, primes):
visited.add((x, y))
if number and number > 10 and is_prime(int(number)):
primes[int(number)] += 1
for dx, dy in DIRECTIONS:
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n and (nx, ny) not in visited:
dfs(mat, m, n, nx, ny, number + str(mat[nx][ny]), visited.copy(), primes)
def most_frequent_prime(mat):
m, n = len(mat), len(mat[0])
primes = defaultdict(int)
for i in range(m):
for j in range(n):
dfs(mat, m, n, i, j, str(mat[i][j]), set(), primes)
max_freq = 0
result = -1
for prime, freq in primes.items():
if freq > max_freq or (freq == max_freq and prime > result):
max_freq = freq
result = prime
return result
mat = [[1, 1], [9, 9], [1, 1]]
print(most_frequent_prime(mat)) # Output: 19
import java.util.HashMap;
import java.util.Map;
public class MostFrequentPrime {
private static final int[][] DIRECTIONS = {
{0, 1}, {1, 1}, {1, 0}, {1, -1},
{0, -1}, {-1, -1}, {-1, 0}, {-1, 1}
};
public static boolean isPrime(int n) {
if (n <= 1) return false;
if (n <= 3) return n > 10;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return n > 10;
}
public static void dfs(int[][] mat, int m, int n, int x, int y, String number, boolean[][] visited, Map<Integer, Integer> primes) {
visited[x][y] = true;
int num = Integer.parseInt(number);
if (num > 10 && isPrime(num)) {
primes.put(num, primes.getOrDefault(num, 0) + 1);
}
for (int[] dir : DIRECTIONS) {
int nx = x + dir[0];
int ny = y + dir[1];
if (nx >= 0 && nx < m && ny >= 0 && ny < n && !visited[nx][ny]) {
dfs(mat, m, n, nx, ny, number + mat[nx][ny], visited, primes);
}
}
visited[x][y] = false;
}
public static int mostFrequentPrime(int[][] mat) {
int m = mat.length;
int n = mat[0].length;
boolean[][] visited = new boolean[m][n];
Map<Integer, Integer> primes = new HashMap<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
dfs(mat, m, n, i, j, String.valueOf(mat[i][j]), visited, primes);
}
}
int maxFreq = 0;
int result = -1;
for (Map.Entry<Integer, Integer> entry : primes.entrySet()) {
if (entry.getValue() > maxFreq || (entry.getValue() == maxFreq && entry.getKey() > result)) {
maxFreq = entry.getValue();
result = entry.getKey();
}
}
return result;
}
public static void main(String[] args) {
int[][] mat = {{1, 1}, {9, 9}, {1, 1}};
System.out.println(mostFrequentPrime(mat)); // Output: 19
}
}The solution uses a recursive DFS function to explore paths from each cell. Each new digit forms and extends numbers by traversing in specified directions, and these paths are checked for prime conditions (>10). The function counts these primes and determines the one with the highest frequency.
Time Complexity: O(8^(m * n)) - Due to exponential path exploration in recursion.
Space Complexity: O(m * n) for recursion stack and prime tracking.
Approach 2: Backtracking Focused on Matrix Paths
This approach introduces backtracking to optimize search in the matrix for prime number paths. For every starting cell, the method attempts all potential valid paths holding a number construct as it explores, abandoning paths prematurely when they're deemed non-promising.
#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
using namespace std;
const vector<pair<int, int>> DIRECTIONS = {{0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}};
bool isPrime(int n) {
if (n <= 1) return false;
if (n <= 3) return n > 10;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return n > 10;
}
void explorePaths(vector<vector<int>>& mat, int m, int n, int x, int y, string currentNumber, vector<vector<bool>>& visited, unordered_map<int, int>& primeCount) {
visited[x][y] = true;
int num = stoi(currentNumber);
if (num > 10 && isPrime(num)) {
primeCount[num]++;
}
for (const auto& d : DIRECTIONS) {
int nx = x + d.first;
int ny = y + d.second;
if (nx >= 0 && ny >= 0 && nx < m && ny < n && !visited[nx][ny]) {
explorePaths(mat, m, n, nx, ny, currentNumber + to_string(mat[nx][ny]), visited, primeCount);
}
}
visited[x][y] = false;
}
int mostFrequentPrime(vector<vector<int>>& mat) {
int m = mat.size();
int n = mat[0].size();
unordered_map<int, int> primeCount;
vector<vector<bool>> visited(m, vector<bool>(n, false));
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
explorePaths(mat, m, n, i, j, to_string(mat[i][j]), visited, primeCount);
}
}
int result = -1;
int maxCount = 0;
for (const auto& pair : primeCount) {
if (pair.second > maxCount || (pair.second == maxCount && pair.first > result)) {
maxCount = pair.second;
result = pair.first;
}
}
return result;
}
int main() {
vector<vector<int>> mat = {{9, 7, 8}, {4, 6, 5}, {2, 8, 6}};
cout << mostFrequentPrime(mat) << endl; // Output: 97
return 0;
}
const DIRECTIONS = [
[0, 1], [1, 1], [1, 0], [1, -1],
[0, -1], [-1, -1], [-1, 0], [-1, 1]
];
function isPrime(n) {
if (n <= 1) return false;
if (n <= 3) return n > 10;
if (n % 2 === 0 || n % 3 === 0) return false;
for (let i = 5; i * i <= n; i += 6) {
if (n % i === 0 || n % (i + 2) === 0) return false;
}
return n > 10;
}
function dfs(mat, m, n, x, y, number, visited, primes) {
visited[x][y] = true;
let num = parseInt(number);
if (num > 10 && isPrime(num)) {
primes[num] = (primes[num] || 0) + 1;
}
for (const [dx, dy] of DIRECTIONS) {
const nx = x + dx;
const ny = y + dy;
if (nx >= 0 && ny >= 0 && nx < m && ny < n && !visited[nx][ny]) {
dfs(mat, m, n, nx, ny, number + String(mat[nx][ny]), JSON.parse(JSON.stringify(visited)), primes);
}
}
visited[x][y] = false;
}
function mostFrequentPrime(mat) {
const m = mat.length;
const n = mat[0].length;
const primes = {};
const visited = Array.from({ length: m }, () => Array(n).fill(false));
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
dfs(mat, m, n, i, j, String(mat[i][j]), visited, primes);
}
}
let maxFreq = 0;
let result = -1;
for (const [prime, freq] of Object.entries(primes)) {
if (freq > maxFreq || (freq === maxFreq && Number(prime) > result)) {
maxFreq = freq;
result = Number(prime);
}
}
return result;
}
const mat = [[9, 7, 8], [4, 6, 5], [2, 8, 6]];
console.log(mostFrequentPrime(mat)); // Output: 97The C++ implementation enhances path exploration by using a backtracking strategy to navigate potential paths of digits forming numbers, checking for primes only when paths gather enough digits. This incremental path decision prevents excessive memory use and focuses computational effort on promising paths.
Time Complexity: O(8^(m * n)) - Due to potential path exploration.
Space Complexity: O(m * n) for embedding matrix and track past visited configurations.
Approach 3: Hash Table + Enumeration
We can use a hash table to count the frequency of each prime number greater than 10.
For each cell, we can start from it, generate a number along one of the 8 directions, and then determine whether the generated number is a prime number greater than 10. If it is, we add it to the hash table.
Finally, we traverse the hash table to find the prime number with the highest frequency. If there are multiple prime numbers with the highest frequency, we return the largest one.
The time complexity is O(m times n times max(m, n) times {10}^{\frac{max(m, n)}{2}}), and the space complexity is O(m times n times max(m, n)). Here, m and n are the number of rows and columns of mat, respectively.
function mostFrequentPrime(mat: number[][]): number {
const m: number = mat.length;
const n: number = mat[0].length;
const cnt: Map<number, number> = new Map();
const isPrime = (x: number): boolean => {
for (let i = 2; i <= x / i; ++i) {
if (x % i === 0) {
return false;
}
}
return true;
};
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
for (let a = -1; a <= 1; ++a) {
for (let b = -1; b <= 1; ++b) {
if (a === 0 && b === 0) {
continue;
}
let [x, y, v] = [i + a, j + b, mat[i][j]];
while (x >= 0 && x < m && y >= 0 && y < n) {
v = v * 10 + mat[x][y];
if (isPrime(v)) {
cnt.set(v, (cnt.get(v) || 0) + 1);
}
x += a;
y += b;
}
}
}
}
}
let [ans, mx] = [-1, 0];
cnt.forEach((x, v) => {
if (mx < x || (mx === x && ans < v)) {
mx = x;
ans = v;
}
});
return ans;
}func mostFrequentPrime(mat [][]int) int {
m, n := len(mat), len(mat[0])
cnt := make(map[int]int)
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
for a := -1; a <= 1; a++ {
for b := -1; b <= 1; b++ {
if a == 0 && b == 0 {
continue
}
x, y, v := i+a, j+b, mat[i][j]
for x >= 0 && x < m && y >= 0 && y < n {
v = v*10 + mat[x][y]
if isPrime(v) {
cnt[v]++
}
x += a
y += b
}
}
}
}
}
ans, mx := -1, 0
for v, x := range cnt {
if mx < x || (mx == x && ans < v) {
mx = x
ans = v
}
}
return ans
}
func isPrime(n int) bool {
for i := 2; i <= n/i; i++ {
if n%i == 0 {
return false
}
}
return true
}Complexity comparison
| Approach | Complexity |
|---|---|
| Depth First Search (DFS) with Path Tracking | Time Complexity: O(8^(m * n)) - Due to exponential path exploration in recursion. Space Complexity: O(m * n) for recursion stack and prime tracking. |
| Backtracking Focused on Matrix Paths | Time Complexity: O(8^(m * n)) - Due to potential path exploration. Space Complexity: O(m * n) for embedding matrix and track past visited configurations. |
| Hash Table + Enumeration | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| DFS with Path Tracking | O(m * n * k) | O(P) | General case when enumerating all directional number formations in the grid |
| Backtracking on Matrix Paths | O(m * n * k) | O(P + k) | Useful when modeling the problem explicitly as recursive path exploration |
Frequently asked questions
Is Most Frequent Prime easy or hard?
Most Frequent Prime is considered a Medium difficulty problem. The challenge comes from combining matrix traversal, incremental number construction, prime checking, and frequency tracking. Candidates comfortable with DFS and hash maps typically solve it without major difficulty.
Most Frequent Prime Python/Java solution
Python and Java implementations usually follow the same pattern: iterate over every grid cell, explore directional paths using DFS or loops, construct numbers incrementally, and store counts in a hash map. A helper function checks whether a number is prime before updating the frequency.
How to solve Most Frequent Prime in O(n)?
A strict O(n) solution is not feasible because the algorithm must explore multiple paths from each cell in the grid. The optimal practical approach is O(m * n * k) using DFS or directional enumeration. Efficient prime checking and incremental number construction keep the runtime manageable.
What is the best approach for Most Frequent Prime?
The most effective approach is DFS-based enumeration from every grid cell while forming numbers incrementally. Each new value is checked for primality and recorded in a hash map. This method systematically explores all valid digit sequences and tracks frequencies efficiently with O(m * n * k) time complexity.
Is Most Frequent Prime asked at Google/Amazon/Meta?
Matrix traversal and number construction problems appear frequently in interviews at companies like Amazon, Google, and Meta. While this exact problem may not always appear, the underlying patterns—grid traversal, hashing for frequency counting, and prime checking—are common interview topics.
What data structure is used in Most Frequent Prime?
The key data structure is a hash map that stores prime numbers as keys and their frequencies as values. The algorithm also relies on matrix traversal techniques and directional movement across the grid. Prime validation uses basic number theory checks.
What is the time complexity of Most Frequent Prime?
The overall time complexity is O(m * n * k), where m and n are the grid dimensions and k is the maximum length of a path explored in one direction. Each step forms a new number and performs a prime check, typically up to the square root of the number. Space complexity is mainly O(P) for storing prime frequencies.
