特定范围内最常见的数字

时间:2015-04-17 22:11:42

标签: performance algorithm time-limiting

首先:降级之前这不是我的家庭作业,这个问题属于codingbat或eulerproject或其他网站。我不是要求你给我一个完整的和编码的答案我要求你给我一些想法帮助我。

稍后,我遇到了这个问题的时间限制问题。我实际上解决了它,但我的解决方案太慢了。它需要在0到1秒内完成。在最坏的情况下,我的代码消耗超过8秒。如果你可以帮助我一些想法,或者如果你能给我一个更准确的解决方案伪代码等,我会非常感激。

首先输入意味着我们要处理多少次。稍后,用户输入两个数字 [X,Y],(0 我们需要计算这两个数字X和Y范围内的最频繁数字。(包括X和Y)此外,如果多个数字的最大频率与我们打印最小的数字相同。

举例说明:

用户首先输入测试用例数:7

用户输入X和Y(第一个测试用例):0 21

现在我确实打开了我的解决方案中的所有数字你可能有另一个想法,你可以自由使用它但是给你一个提示:我们需要对待这样的数字:0 1 2 3 ... (这里我们应该为所有人打开10 1 0 相同) 1 0 1 1 1 2 1 3 ... 1 9 2 0 2 1比我们在0到21之间显示最频繁的数字(在这种情况下:1)

更多示例:(如果您想检查解决方案的测试用例)

X: 7 Y: 956 结果: 1

X: 967 Y: 8000 结果: 7

X: 420 Y: 1000 结果: 5

到目前为止,这是我的代码:

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;
    }
}
}

正如您所看到的,如果用户输入X:0 Y:1000000,如8 - 9秒,则需要太长时间。但它应该在1秒内回复。谢谢你查一下......

1 个答案:

答案 0 :(得分:0)

列出所有数字然后计算它们是一种非常缓慢的方法。

有一些简单的案例:

  1. X = 10nX = 10n+1-1n > 0):
    数字19出现10n + n⋅(10n-10n-1)次,0出现n⋅(10n-10n-1)次。

    E.g。

    • 10,99:数字19出现19次,0出现9次。
    • 100,999:数字19出现了280次,0出现了180次。
  2. X = a⋅10ⁿY = (a+1)⋅10ⁿ-11 ≤ a ≤ 9):
    a以外的所有数字均显示为n⋅10n-1,数字a显示10n + n⋅10n-1次。

    E.g。

    • 10,19:除1以外的所有数字都出现一次,1出现11次。
    • 20,299:除2以外的所有数字均显示20次,2显示120次。
  3. 在这种情况下,您可以将输入拆分为子案例。例如。

    1. X = 0Y = 21。把它拆分成
      • X₁ = 0Y₁ = 9(特殊情况,但非常简单),
      • X₂ = 10Y₂ = 19(案例2),
      • X₃ = 20Y₃ = 21(案例3)
    2. X = 0Y = 3521。把它拆分成
      • X₁ = 0Y₁ = 9(特殊情况,但非常简单),
      • X₂ = 10Y₂ = 99(案例1),
      • X₃ = 100Y₃ = 999(案例1),
      • X₄ = 1000Y₄ = 1999(案例2),
      • X₅ = 2000Y₅ = 2999(案例2),
      • X₆ = 3000Y₆ = 3521(案例3)
    3. 我把案例3打开了。该案例看起来像X = a⋅10ⁿY = a⋅10ⁿ + b1 ≤ a ≤ 90 ≤ b < 10ⁿ)。 在这里,您知道数字a b - 次数加上0到b的出现次数。由于XYn+1个数字,b的数字为n,前导零。

      案例3的缺失部分必须由读者填写。