Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructing the largest number possible by rearranging a list

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.

like image 748
user2012686 Avatar asked Jan 25 '13 23:01

user2012686


People also ask

How do you find the largest number formed from an array of numbers?

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.

Which function will you use to find the largest number from a list of numbers?

Answer. Explanation: The Excel MAX function returns the largest numeric value in a range of values.

What will be the most efficient approach to find the largest number in a list of twenty numbers?

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.

How do you rearrange given numbers to form the biggest 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.

How to find the largest value of an array of numbers?

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.

How can I generate the largest number possible?

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.

Which arrangement gives the largest value of the given numbers?

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.


3 Answers

sorted(x, cmp=lambda a, b: -1 if str(b)+str(a) < str(a)+str(b) else 1)

like image 50
mmgp Avatar answered Oct 23 '22 10:10

mmgp


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:

  • comparing 9 and 95: compare 999 and 9595 instead and thus 999 comes first.
  • comparing 1 and 17: compare 111 and 1717 instead and thus 1717 comes first.
  • comparing 132 and 13: compare 132132 and 1313 instead and thus 132132 comes first.
  • comparing 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).

like image 36
Martijn Pieters Avatar answered Oct 23 '22 08:10

Martijn Pieters


Hint one: you concatenate strings, not integers. Hint two: itertools.permutations().

like image 5
Russell Borogove Avatar answered Oct 23 '22 08:10

Russell Borogove