Given a string of numbers and a number of multiplication operators, what is the highest number one can calculate?

后端 未结 9 1551
醉话见心
醉话见心 2021-01-30 11:22

This was an interview question I had and I was embarrassingly pretty stumped by it. Wanted to know if anyone could think up an answer to it and provide the big O notation for it

相关标签:
9条回答
  • 2021-01-30 12:13

    I'm pretty sure that the answer is to simply put the *s right before the biggest digits, so that the largest digit have the biggest impact. For example, if we have

     1826456903521651 
    

    and we have five multiplications, this would be the answer.

     1*82*645*6*903521*651 
    

    So the running time would be linear.

    Edit: Okay, so this is wrong. We have two counterexamples.

    0 讨论(0)
  • 2021-01-30 12:17

    Here's an iterative dynamic programming solution.

    As opposed to the recursive version (which should have a similar running time).

    The basic idea:

    A[position][count] is the highest number that can be obtained ending at position position, using count multiplications.

    So:

    A[position][count] = max(for i = 0 to position
                               A[i][count-1] * input.substring(i, position))
    

    Do this for each position and each count, then multiply each of these at the required number of multiplications with the entire remaining string.

    Complexity:

    Given a string |s| with m multiplication operators to be inserted...

    O(m|s|2g(s)) where g(s) is the complexity of multiplication.

    Java code:

    static long solve(String digits, int multiplications)
    {
      if (multiplications == 0)
         return Long.parseLong(digits);
    
      // Preprocessing - set up substring values
      long[][] substrings = new long[digits.length()][digits.length()+1];
      for (int i = 0; i < digits.length(); i++)
      for (int j = i+1; j <= digits.length(); j++)
         substrings[i][j] = Long.parseLong(digits.substring(i, j));
    
      // Calculate multiplications from the left
      long[][] A = new long[digits.length()][multiplications+1];
      A[0][0] = 1;
      for (int i = 1; i < A.length; i++)
      {
         A[i][0] = substrings[0][i];
         for (int j = 1; j < A[0].length; j++)
         {
            long max = -1;
            for (int i2 = 0; i2 < i; i2++)
            {
               long l = substrings[i2][i];
               long prod = l * A[i2][j-1];
               max = Math.max(max, prod);
            }
            A[i][j] = max;
         }
      }
    
      // Multiply left with right and find maximum
      long max = -1;
      for (int i = 1; i < A.length; i++)
      {
         max = Math.max(max, substrings[i][A.length] * A[i][multiplications]);
      }
      return max;
    }
    

    A very basic test:

    System.out.println(solve("99287", 1));
    System.out.println(solve("99287", 2));
    System.out.println(solve("312", 1));
    

    Prints:

    86304
    72036
    62
    

    Yes, it just prints the maximum. It's not too difficult to have it actually print the sums, if required.

    0 讨论(0)
  • 2021-01-30 12:20

    The java version, though Python already showed its functional advantage and beat me:

    private static class Solution {
        BigInteger product;
        String expression;
    }
    
    private static Solution solve(String digits, int multiplications) {
        if (digits.length() < multiplications + 1) {
            return null; // No solutions
        }
        if (multiplications == 0) {
            Solution solution = new Solution();
            solution.product = new BigInteger(digits);
            solution.expression = digits;
            return solution;
        }
        // Position of first '*':
        Solution max = null;
        for (int i = 1; i < digits.length() - (multiplications - 1); ++i) {
            BigInteger n = new BigInteger(digits.substring(0, i));
            Solution solutionRest = solve(digits.substring(i), multiplications - 1);
            n = n.multiply(solutionRest.product);
            if (max == null || n.compareTo(max.product) > 0) {
                solutionRest.product = n;
                solutionRest.expression = digits.substring(0, i) + "*"
                    + solutionRest.expression;
                max = solutionRest;
            }
        }
        return max;
    }
    
    private static void test(String digits, int multiplications) {
        Solution solution = solve(digits, multiplications);
        System.out.printf("%s %d -> %s = %s%n", digits, multiplications,
                solution.expression, solution.product.toString());
    }
    
    public static void main(String[] args) {
        test("1826456903521651", 5);
    }
    

    Output

    1826456903521651 5 -> 182*645*6*903*521*651 = 215719207032420
    
    0 讨论(0)
提交回复
热议问题