Say I have an array of positive whole integers; I'd like to manipulate the order so that the concatenation of the resultant array is the largest number possible. For example [97, 9, 13]
results in 99713
; [9,1,95,17,5]
results in 9955171
. I'm not sure of an answer.
Suppose an array exists that contains different unsorted numbers. To form the largest number from the given numbers, sort the array in descending order and then simply combine it into one whole number.
Answer. Explanation: The Excel MAX function returns the largest numeric value in a range of values.
This is Expert Verified Answer All the numbers in the list are arranged in the descending order such that the largest number comes at the beginning and so on. Now, the number which occur at the first position is the required largest number.
The problem “Arrange given numbers to form the biggest number” asks to rearrange the array in such a manner that the output should be the maximum value which can be made with those numbers of an array. Explanation: We have concatenated numbers with each other such that it produces the highest value.
Given an array of numbers, arrange them in a way that yields the largest value. For example, if the given numbers are {54, 546, 548, 60}, the arrangement 6054854654 gives the largest value. And if the given numbers are {1, 34, 3, 98, 9, 76, 45, 4}, then the arrangement 998764543431 gives the largest value.
I'm reasonably certain the largest number will be formed by sorting the digits in descending order. Assuming that's correct, the best-case complexity is linear--you can generate the digits, then sort them with a bucket sort (aka. counting sort), and finally generate the result--all linear, so the overall result is linear.
And if the given numbers are {1, 34, 3, 98, 9, 76, 45, 4}, then the arrangement 998764543431 gives the largest value. Recommended: Please solve it on “ PRACTICE ” first, before moving on to the solution. A simple solution that comes to our mind is to sort all numbers in descending order, but simply sorting doesn’t work.
sorted(x, cmp=lambda a, b: -1 if str(b)+str(a) < str(a)+str(b) else 1)
Intuitively, we can see that a reverse sort of single digit numbers would lead to the higest number:
>>> ''.join(sorted(['1', '5', '2', '9'], reverse=True))
'9521'
so reverse sorting should work. The problem arises when there are multi-digit snippets in the input. Here, intuition again lets us order 9
before 95
and 17
before 1
, but why does that work? Again, if they had been the same length, it would have been clear how to sort them:
95 < 99
96 < 97
14 < 17
The trick then, is to 'extend' shorter numbers so they can be compared with the longer ones and can be sorted automatically, lexicographically. All you need to do, really, is to repeat the snippet to beyond the maximum length:
9
and 95
: compare 999
and 9595
instead and thus 999
comes first.1
and 17
: compare 111
and 1717
instead and thus 1717
comes first.132
and 13
: compare 132132
and 1313
instead and thus 132132
comes first.23
and 2341
: compare 232323
and 23412341
instead and thus 2341
comes first.This works because python only needs to compare the two snippets until they differ somewhere; and it's (repeating) matching prefixes that we need to skip when comparing two snippets to determine which order they need to be in to form a largest number.
You only need to repeat a snippet until it is longer than the longest snippet * 2 in the input to guarantee that you can find the first non-matching digit when comparing two snippets.
You can do this with a key
argument to sorted()
, but you need to determine the maximum length of the snippets first. Using that length, you can 'pad' all snippets in the sort key until they are longer than that maximum length:
def largestpossible(snippets):
snippets = [str(s) for s in snippets]
mlen = max(len(s) for s in snippets) * 2 # double the length of the longest snippet
return ''.join(sorted(snippets, reverse=True, key=lambda s: s*(mlen//len(s)+1)))
where s*(mlen//len(s)+1)
pads the snippet with itself to be more than mlen
in length.
This gives:
>>> combos = {
... '12012011': [1201, 120, 1],
... '87887': [87, 878],
... '99713': [97, 9, 13],
... '9955171': [9, 1, 95, 17, 5],
... '99799713': [97, 9, 13, 979],
... '10100': [100, 10],
... '13213': [13, 132],
... '8788717': [87, 17, 878],
... '93621221': [936, 21, 212],
... '11101110': [1, 1101, 110],
... }
>>> def test(f):
... for k,v in combos.items():
... print '{} -> {} ({})'.format(v, f(v), 'correct' if f(v) == k else 'incorrect, should be {}'.format(k))
...
>>> test(largestpossible)
[97, 9, 13] -> 99713 (correct)
[1, 1101, 110] -> 11101110 (correct)
[936, 21, 212] -> 93621221 (correct)
[13, 132] -> 13213 (correct)
[97, 9, 13, 979] -> 99799713 (correct)
[87, 878] -> 87887 (correct)
[1201, 120, 1] -> 12012011 (correct)
[100, 10] -> 10100 (correct)
[9, 1, 95, 17, 5] -> 9955171 (correct)
[87, 17, 878] -> 8788717 (correct)
Note that this solution is a) 3 lines short and b) works on Python 3 as well without having to resort to functools.cmp_to_key()
and c) does not bruteforce the solution (which is what the itertools.permutations
option does).
Hint one: you concatenate strings, not integers.
Hint two: itertools.permutations()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With