-2

First of all: before you downgrade THIS IS NOT MY HOMEWORK, this question belongs to codingbat or eulerproject or another website. I am NOT asking you to give me a fully completed and coded answer I am asking you to give me some ideas to HELP me.

Later on, I am having a time limit trouble with this problem. I actually solved it but my solution is too slow. It needs to be done within at 0 to 1 second. In the worst case scenario my code consumes more than 8 seconds. If you could help me with some ideas or if you could show me a more accurate solution pseudo code etc. I would really appreciate it.

First input means how many times we are going to process. Later on, user enters two numbers [X, Y], (0 < X < Y < 100000) We need to compute the most frequent digit in the range of these two numbers X and Y. (including X and Y) Besides, If multiple digits have the same maximum frequency than we suppose to print the smallest of them.

To illustrate:

User first enters number of test cases: 7

User enters X and Y(first test case): 0 21

Now I did open all digits in my solution you may have another idea you are free to use it but to give you a hint: We need to treat numbers like this: 0 1 2 3 ... (here we should open 10 as 1 and 0 same for all of them) 1 0 1 1 1 2 1 3 ... 1 9 2 0 2 1 than we show the most frequent digit between 0 and 21 (In this case: 1)

More examples: (Test cases if you want to check your solution)

X: 7 Y: 956 Result: 1

X: 967 Y: 8000 Result: 7

X: 420 Y: 1000 Result: 5 etc.

Here's my code so far:

package most_frequent_digit;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

public class Main
{
public static int secondP = 0;

public static void getPopularElement(int[] list)
{
    Map<Integer, Integer> map = new HashMap<Integer, Integer>();
    for (Integer nextInt : list)
    {
        Integer count = map.get(nextInt);
        if (count == null)
        {
            count = 1;
        } else
        {
            count = count + 1;
        }
        map.put(nextInt, count);
    }

    Integer mostRepeatedNumber = null;
    Integer mostRepeatedCount = null;
    Set<Integer> keys = map.keySet();
    for (Integer key : keys)
    {
        Integer count = map.get(key);
        if (mostRepeatedNumber == null)
        {
            mostRepeatedNumber = key;
            mostRepeatedCount = count;
        } else if (count > mostRepeatedCount)
        {
            mostRepeatedNumber = key;
            mostRepeatedCount = count;
        } else if (count == mostRepeatedCount && key < mostRepeatedNumber)
        {
            mostRepeatedNumber = key;
            mostRepeatedCount = count;
        }
    }

    System.out.println(mostRepeatedNumber);
}

public static void main(String[] args)
{
    @SuppressWarnings("resource")
    Scanner read = new Scanner(System.in);
    int len = read.nextInt();

    for (int w = 0; w < len; w++)
    {
        int x = read.nextInt();
        int y = read.nextInt();
        String list = "";

        for (int i = x; i <= y; i++)
        {
            list += i;
        }
        String newList = "";

        newList += list.replaceAll("", " ").trim();
        int[] listArr = new int[list.length()];

        for (int j = 0; j < newList.length(); j += 2)
        {
            listArr[secondP] = Character.getNumericValue(newList.charAt(j));
            secondP++;
        }

        getPopularElement(listArr);
        secondP = 0;
    }
}
}

As you can see it takes too long if user enters X: 0 Y: 1000000 like 8 - 9 seconds. But it supposed to return answer in 1 second. Thanks for checking...

AbcAeffchen
  • 14,400
  • 15
  • 47
  • 66
doppler
  • 53
  • 1
  • 1
  • 6
  • What is the source of this problem? It looks like this was taken from a competitive programming site. – Douglas Zare Apr 17 '15 at 22:16
  • @Douglas Yes it is from a programming site but I can't remember where exactly. I had marked it as unsolved problem in Eclipse and there are requirements above in a block comment. – doppler Apr 17 '15 at 22:20
  • I check time and print it to console. It takes too long unfortunately. – doppler Apr 17 '15 at 22:23
  • 1
    You should figure out the source and edit the problem to include the source, with a link if possible. Otherwise, it looks like one of the many attempts to get StackOverflow to do someone's homework or to solve a contest problem so that someone who can't solve it can get credit. – Douglas Zare Apr 17 '15 at 22:24
  • @Douglas thank you for your response. I'm afraid I can't find the source because I really don't remember it. It can be: codingbat.com koduesi.com codegolf.com Eulerproject etc. You are right of course I should share the source. I am not even a computer science student though my word doesn't prove anything after all. Next time I'll be more careful. Thanks for your answer again. – doppler Apr 17 '15 at 22:37
  • I still have no idea why 7 people downgraded this question. – doppler Apr 18 '15 at 12:12
  • Doppler, there are currently only 6 down votes, not 8. Perhaps after the edits, some down votes were removed. Good. It's still not a great question, but it is better than before. Sometimes, after a lot of earlier votes, people don't read the question carefully before voting, so it helps to make a question or answer good in the first place. You could improve it by stating that you are doing a brute force iteration over all integers in the range, by using comments or descriptive variable names in your code, and by posting the important code only. That would make it easier to read. – Douglas Zare Apr 18 '15 at 12:22

1 Answers1

0

Listing all digits and then count them is a very slow way to do this.

There are some simple cases:

  1. X = 10n, X = 10n+1-1 (n > 0) :
    The digits 1 to 9 are appearing 10n + n⋅(10n-10n-1) times, 0 appears n⋅(10n-10n-1) times.

    E.g.

    • 10, 99: the digits 1 to 9 are appearing 19 times, 0 appears 9 times.
    • 100, 999: the digits 1 to 9 are appearing 280 times, 0 appears 180 times.
  2. X = a⋅10ⁿ, Y = (a+1)⋅10ⁿ-1 (1 ≤ a ≤ 9):
    All digits except for a appears n⋅10n-1, the digit a appears 10n + n⋅10n-1 times.

    E.g.

    • 10, 19: all digits except for 1 appear one time, 1 appears 11 times.
    • 20, 299: all digits except for 2 appear 20 times, 2 appears 120 times.

With this cases you can split off the input into sub cases. E.g.

  1. X = 0, Y = 21. Split it up into
    • X₁ = 0, Y₁ = 9 (special case, but very simple),
    • X₂ = 10, Y₂ = 19 (case 2),
    • X₃ = 20, Y₃ = 21 (case 3)
  2. X = 0, Y = 3521. Split it up into
    • X₁ = 0, Y₁ = 9 (special case, but very simple),
    • X₂ = 10, Y₂ = 99 (case 1),
    • X₃ = 100, Y₃ = 999 (case 1),
    • X₄ = 1000, Y₄ = 1999 (case 2),
    • X₅ = 2000, Y₅ = 2999 (case 2),
    • X₆ = 3000, Y₆ = 3521 (case 3)

I left case 3 open. The case looks like X = a⋅10ⁿ, Y = a⋅10ⁿ + b (1 ≤ a ≤ 9, 0 ≤ b < 10ⁿ). Here you know you get the digit a b-times plus the number of appearances in 0 to b. Since X and Y are n+1 digit numbers, b has n digits, with leading zeros.

The missing parts of case 3 have to be filled by the reader.

AbcAeffchen
  • 14,400
  • 15
  • 47
  • 66
  • Thank you for your answer. Now I am improving my code as you suggested but I still think there must be a lot easier way to compute this(I mean max. 20 lines of solution etc.). Unfortunately a google search doesn't reveal any work on this problem. Thanks once again for your response It helped a lot. I'll vote up as soon as possible :) – doppler Apr 18 '15 at 12:09
  • @doppler What I wrote can be used to improve the way to count the appearance of the digits. But maybe there exist a faster way, if you just want to know, which digit appears the most, but not how often it appears exactly. E.g. `X = 950, Y = 2200`. Since there are 1000 numbers that begin with a `1`, this is the digit that appears the most. – AbcAeffchen Apr 19 '15 at 19:07