1

Given two number a and b (1 <= a <= b <= 10^6). Find most frequent digit among all prime numbers between a and b inclusive. if frequency is same print highest digit.

Example: from 1 to 20, prime numbers are - 2, 3, 5, 7, 11, 13, 17, 19. Here 2, 5, 9 occur only once, 3, 7 occur twice, and 1 occurs 5 times. So the result is 1.

One basic approach is:

  • In the range [a, b] - find all prime numbers.
  • Take one count array to count occurrences from 0 to 9.
  • For all the prime numbers in the range, extract all the digits and increment the count for the digits accordingly in the count array.
  • Find out max from the count array.

But this is inefficient for a large range say [1, 1000000].

Is there any efficient method to accomplish this?

coderx
  • 509
  • 6
  • 22

2 Answers2

4

Do a sieve of Eratosthenes to find all the prime numbers in the range 0, 106. This can be done quite fast(in under 1 sec on a modest machine). Use 10 auxiliary arrays - one for each of the digits each of the arrays with size 106. If a number is not prime have 0 stored all 10 arrays. If a number is prime, store in each array the number of times the given digit appears in the number. After that cycle over each of the arrays and accumulate prefix sums of the number of occurrences of the given digit. This can be done quite easily in linear time. Say for digit 3:

for (int i = 1; i < n; ++i) {
   a3[i] += a3[i-1];
}

Having those arrays you can count the number of occurrences of each digit in a specified interval in constant time. Namely the number of occurrences of 3 in the interval [x,y] is a3[y] - a3[x-1](take care of special case when x is 0).

The computational complexity of this algorithm is the same as the one of sieve of Eratosthenes for the precomputation and constant for each query. The memory complexity is linear. You can improve the memory overhead by only storing values for the prime numbers in the auxiliary arrays, thus having them with size equal of the number of prime numbers up to 106 if need be. However this would make the implementation slightly trickier.

Pang
  • 9,564
  • 146
  • 81
  • 122
Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
  • I'm don't see the point of having 10 arrays *of length 10**6*. Just have one array of length 10 initialized to all zeroes, each entry representing a count of how many times that digit appears. Then one pass through all the primes is sufficient to compute the counts. – President James K. Polk Oct 04 '15 at 15:13
0
function writeOutput(left, right) {

let digitCount = new Array(10);
digitCount.fill(0)


for(let num = left ; num <= right; num++){
    if(isPrime(num)){
        let copyNum = num;
        while (copyNum > 0){
            let d = copyNum % 10;
            digitCount[d]++;
            copyNum = copyNum / 10;
        }
    }
}


 let maxCount = 0;

 let maxNum = 0;

 for (let j = 0; j < digitCount.length; j++){
   if(digitCount[j] > maxCount){
    maxCount = digitCount[j];
    maxNum = j;
   }
 }
if(maxCount == 1){
    for(let k = digitCount.length - 1; k > 0; k--){
      if(digitCount[k] > 0){
        maxNum = k;
        break;
       }
    }
  } else if( maxCount > 1){
    return maxNum;
 } else {
    maxNum = -1;
 }

 return maxNum

 }
   function isPrime(n){
      for(let i = 2; i * i <= n; i++){
         if(n % i == 0){
           return false
         }
     }
     return true
  }