4

There is well known algorithmic problem, given array of numbers e.g. [1, 20, 3, 14] arrange numbers in such a way that they form biggest number possible, in this case 320141.

There is plenty of solutions on SO and other sites, using the following algorithm:

String[] strs = new String[nums.length];
for(int i=0; i<nums.length; i++){
    strs[i] = String.valueOf(nums[i]);
}

Arrays.sort(strs, new Comparator<String>(){
    public int compare(String s1, String s2){
        String leftRight = s1+s2;
        String rightLeft = s2+s1;
        return -leftRight.compareTo(rightLeft);

    }
});

StringBuilder sb = new StringBuilder();
for(String s: strs){
    sb.append(s);
}

return sb.toString();

It certainly works, but I cannot find a formal proof of this algorithm. There is one answer on quora, but I wouldn't call it a formal proof.

Does anyone can give me a sketch of proof or reference some book or article? How one can get on this solution from the original problem?

PS I tried to solve original problem but my solution was wrong, I couldn't get it right, and now I could not fully understand solution.

Msp
  • 2,493
  • 2
  • 20
  • 34
csharpfolk
  • 4,124
  • 25
  • 31
  • the answer on quora seems to be quite formal to me, though indeed just a sketch. what more do you want? – cobarzan Jan 05 '16 at 18:39
  • cobarzan I tried to follow quora proof but can't get some steps, maybe I need something more formal or with small steps. – csharpfolk Jan 05 '16 at 18:43

2 Answers2

3

Regarding notation: I will use pipes to separate the numbers so it's easier to see the sequence of numbers and the resulting number at the same time: 3|20|14|1

Let us assume for the moment that the relation -- let's call it R represented by the <= operator -- that is defined by the compare function is a total order. It is determined by the expression

-(a+b).compareTo(b+a)

Intuitively it says that if we have two numbers a and b and b|a is larger than a|b, b should get a higher rank than a, i.e. it should occur left of a in the solution. If a|b is larger than b|a, it's the other way round. If a|b = b|a, the order does not matter.

One important thing to note is that this relation not only affects two numbers a and b considered in isolation but also tells us something about the resulting number the two numbers are embedded in:

If a<=b, then x|a|b|y <= x|b|a|y

with x and y being numbers of arbitrary lengths. In other words: If we have a sequence of numbers and we swap two adjacent numbers a and b with a<=b, the resulting number will be greater or equal afterwards.

Example: 3|14|20|1 <= 3|20|14|1 because 14 <= 20

We can now lead the assumption that the solution is not the one implied by our relation R to a contradiction: Let's assume the solution is some specific sequence not conforming to R. Since R is a total order, we can rearrange the numbers to match R by swapping adjacent elements until the order conforms to R. This reordering can be compared to a bubble sort. However, in each swap operation that leads us to the new order, the resulting number increases! This is clearly a contradiction, so the original order cannot be the the solution.

All that is left to show is that R is a total order, i.e. it is transitive, antisymmetric and total. Since you asked for a sketch of the proof, I'll omit this part. The essential part is proving transitivity, i.e. that

a <= b and b <= c implies a <= c.

lex82
  • 11,173
  • 2
  • 44
  • 69
2

Here's a sketch of the algorithm. For your given list:

[1, 20, 3, 14]

think about how you would find the largest concatenated number.

For the most significant digit, pick the number with the largest initial digit. (In the example, pick the 3 and then the 20. Thus the answer starts with 320.)

The remaining numbers, 1 and 14, start with the same initial digit (namely 1). Which to pick next? This is where the heart of the algorithm, the compare function, comes into play. It will build the numbers and compare which one is lexically larger, that is, 114 versus 141. The negative sign on the return statement will make sure that the bigger number goes first. So the answer would be 320141.

(The algorithm doesn't actually compare the initial digits, but rather, sorts the strings from lexically largest to smallest.)

rajah9
  • 11,645
  • 5
  • 44
  • 57