Constructing the largest number possible by rearranging a list

前端 未结 8 579
后悔当初
后悔当初 2020-12-16 11:53

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 exampl

相关标签:
8条回答
  • 2020-12-16 12:14

    You can do this with some clever sorting.

    If two strings are the same length, choose the larger of the two to come first. Easy.

    If they're not the same length, figure out what would be the result if the best possible combination were appended to the shorter one. Since everything that follows the shorter one must be equal to or less than it, you can determine this by appending the short one to itself until it's the same size as the longer one. Once they're the same length you do a direct comparison as before.

    If the second comparison is equal, you've proven that the shorter string can't possibly be better than the longer one. Depending on what it's paired with it could still come out worse, so the longer one should come first.

    def compare(s1, s2):
        if len(s1) == len(s2):
            return -1 if s1 > s2 else int(s2 > s1)
        s1x, s2x = s1, s2
        m = max(len(s1), len(s2))
        while len(s1x) < m:
            s1x = s1x + s1
        s1x = s1x[:m]
        while len(s2x) < m:
            s2x = s2x + s2
        s2x = s2x[:m]
        return -1 if s1x > s2x or (s1x == s2x and len(s1) > len(s2)) else 1
    
    def solve_puzzle(seq):
        return ''.join(sorted([str(x) for x in seq], cmp=compare))
    
    >>> solve_puzzle([9, 1, 95, 17, 5])
    '9955171'
    >>> solve_puzzle([97, 9, 13])
    '99713'
    >>> solve_puzzle([936, 21, 212])
    '93621221'
    >>> solve_puzzle([87, 17, 878])
    '8788717'
    >>> solve_puzzle([97, 9, 13, 979])
    '99799713'
    

    This should be much more efficient than running through all the permutations.

    0 讨论(0)
  • 2020-12-16 12:17
    import itertools
    nums =  ["9", "97", "13"]
    m = max(("".join(p) for p in itertools.permutations(nums)), key = int)
    

    You can use itertools.permutations as hinted and use the key argument of the max function (which tells which function to apply to each element in order to decide the maximum) after you concat them with the join function.

    It's easier to work with strings to begin with.

    0 讨论(0)
  • 2020-12-16 12:18

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

    0 讨论(0)
  • 2020-12-16 12:19

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

    0 讨论(0)
  • 2020-12-16 12:20

    I don't like the brute force approach to this. It requires a massive amount of computation for large sets.

    You can write your own comparison function for the sorted builtin method, which will return a sorting parameter for any pair, based on any logic you put in the function.

    Sample code:

    def compareInts(a,b):
        # create string representations
        sa = str(a)
        sb = str(b)
    
        # compare character by character, left to right
        # up to first inequality
        # if you hit the end of one str before the other, 
        # and all is equal up til then, continue to next step
        for i in xrange(min(len(sa), len(sb))):
            if sa[i] > sb[i]:
                return 1
            elif sa[i] < sb[i]:
                return -1
    
        # if we got here, they are both identical up to the length of the shorter
        # one.
        # this means we need to compare the shorter number again to the 
        # remainder of the longer
        # at this point we need to know which is shorter
        if len(sa) > len(sb): # sa is longer, so slice it
            return compareInts(sa[len(sb):], sb)
        elif len(sa) < len(sb): # sb is longer, slice it
            return compareInts(sa, sb[len(sa):])
        else:
            # both are the same length, and therefore equal, return 0
            return 0
    
    
    
    def NumberFromList(numlist):
        return int(''.join('{}'.format(n) for n in numlist))
    
    nums = [97, 9, 13, 979]
    sortednums = sorted(nums, cmp = compareInts, reverse = True)
    print nums # [97, 9, 13, 979]
    print sortednums # [9, 979, 97, 13]
    print NumberFromList(sortednums) # 99799713
    
    0 讨论(0)
  • 2020-12-16 12:24

    Well, there's always the brute force approach...

    from itertools import permutations
    lst = [9, 1, 95, 17, 5]
    
    max(int(''.join(str(x) for x in y)) for y in permutations(lst))
    => 9955171
    

    Or this, an adaptation of @Zah's answer that receives a list of integers and returns an integer, as specified in the question:

    int(max((''.join(y) for y in permutations(str(x) for x in lst)), key=int))
    => 9955171
    
    0 讨论(0)
提交回复
热议问题