How to find better algorithm for my prefix matcher algorithm

AverageJoe9000 :

I was solving online problem and the task was something like this:

There are two arrays: numbers and prefixes.

  • Array numbers contains numbers: “+432112345”, “+9990”, “+4450505”
  • Array prefixes contains prefixes: “+4321”, “+43211”, “+7700”, “+4452”, “+4”

Find longest prefix for each number. If no prefix found for number, match with empty string.

For example:

  • “+432112345” matches with the longest prefix “+43211” (not +4321, cause 43211 is longer).
  • “+9990” doesn't match with anything, so empty string "".
  • “+4450505” matches with “+4” (“+4452” doesn’t match because of the 2).

I came up with the most straight forward solution where I loop through each number with each prefix. So each time new number, I check prefixes, if some prefix is longer than last one, I will change.

Map<String, String> numsAndPrefixes = new HashMap<>();

for (String number : A) {
    for (String prefix : B) {
        if (number.contains(prefix)) {
            // if map already contains this number, check for prefixes. 
            // if longer exists, switch longer one
            if (numsAndPrefixes.containsKey(number)) {
                int prefixLength = prefix.length();
                int currentLen = numsAndPrefixes.get(number).length();
                if (prefixLength > currentLen) {
                    numsAndPrefixes.put(number, prefix);
                }
            } else {
                numsAndPrefixes.put(number, prefix);
            }
        } else if (!number.contains(prefix) && !numsAndPrefixes.containsKey(number)){
            numsAndPrefixes.put(number, "");
        }
    }
}

So it will have two for loops. I see that each time I am doing the same job over and over, e.g checking for prefixes. It works, but it is slow. The problem is that I can’t come up with anything better.

Could someone explain how they would approach to find better algorithm?

And more general, how do you proceed if you have somewhat working solution and trying to find better one? What knowledge am I still missing?

Andreas :

I would implement this using a TreeSet and the floor(E e) method.

String[] numbers = { "+432112345", "+9990", "+4450505" };
String[] prefixes = { "+4321", "+43211", "+7700", "+4452", "+4" };

TreeSet<String> prefixSet = new TreeSet<>(Arrays.asList(prefixes));
for (String number : numbers) {
    String prefix = prefixSet.floor(number);
    while (prefix != null && ! number.startsWith(prefix))
        prefix = prefixSet.floor(prefix.substring(0, prefix.length() - 1));
    if (prefix == null)
        prefix = "";
    System.out.println(number + " -> " + prefix);
}

Output

+432112345 -> +43211
+9990 -> 
+4450505 -> +4

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=416165&siteId=1