LeetCode179 Largest Number

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/anlian523/article/details/83114187

题目描述

Largest Number
给定非负整数的列表,返回它们排列成的最大整数。
样例1:

Input: [10,2]
Output: “210”

样例2:

Input: [3,30,34,5,9]
Output: “9534330”

注意:
结果可能很大,所以返回类型应该是字符串。

Python3 基于排序

class Solution:
    # @param {integer[]} nums
    # @return {string}
    def largestNumber(self, nums):
        from functools import cmp_to_key
        key = cmp_to_key(lambda x,y: int(y+x)-int(x+y))
        res = ''.join(sorted(map(str, nums), key=key)).lstrip('0')
        return res or '0'

py3的排序不能用cmp了,必须是基于key的。意思是序列中每个元素最终都会对应一个key值,一般可以是0,1,2…这样的。
解释一下思想,比如3和12,组合起来是312或123,明显312更大,那么3就应该放在12前面。这样就定义了一种比较规则。
我们现在熟知的排序基本都是比较排序(基于比较的排序),所以一般做法是实现一种属于比较排序的排序方法,然后在比较时使用我们新定义的比较规则。
上面代码,只定义了比较规则,排序就不用自己实现了直接使用py的内建函数sorted就行,但需要cmp_to_key转换一下比较规则。

Python3 复制自身

class Solution:
    def largestNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: str
        """
        nums = list(map(str, nums))
        maxLen = max(map(len, nums))
        print(maxLen)
        for i in map(len, nums):
            print(i)
        nums.sort(key = lambda x: x * (maxLen // len(x) + 1), reverse = True)
        
        if nums[0] == '0':
            return '0'
        
        return ''.join(nums)

leetcode上py3最快代码,直接使用的是lambda代表式,可以让每个元素对应到一个key。这句lambda x: x * (maxLen // len(x) + 1)的意思是:

the trick is to compare x+y v.s. y+x, it is equivalent to compare x * m and y * n by repeating x and y many times, the number of repeats can be just long enough to cover the longest one.

翻译一下就是:比较x+y 和 y+x,是和比较x * m 和 y * n是一样的,通过重复x字符串m次、y字符串n次,这个m和n的标准就是要让给x * m 和 y * n的长度能够>=最大长度。
假设最大长度为3,那么比较34和3时,实际比较的是3434和3333,它俩的长度被扩充到能>=最大长度。
(maxLen // len(x) + 1)中,maxLen // len(x)的范围是>=1的,+1是为了保证能够覆盖最大长度,因为这里向下取整了。
在这里插入图片描述
如上实例,由于第一位的不同,在比较第一次就得出了结果。
在这里插入图片描述
如上实例,由于两个数的前两位相同,所以会比较第三次,所以用“34”与“345”复制自身来比较和正常比较方法是一样的。
在这里插入图片描述
如上实例,也是两个数的前两位相同,且三位数的前后都是3,所以导致正常比较过程中第三次比较结果是相同。
原谅我无法用更好的语言来描述这个原理,但上面的图例应该足够读者理解了,如有大佬请不吝赐教。

C++ 基于排序

class Solution {
public:
    string largestNumber(vector<int>& nums) {
       sort(nums.begin(), nums.end(), [](int a, int b){ return to_string(a) + to_string(b) > to_string(b) + to_string(a);});
       string ans = accumulate(nums.begin(), nums.end(), string(), [](string &r, int a){return r + to_string(a);});
       return ans[0] == '0' ? "0" : ans;
       }
};

首先看sort函数的api。前两个参数为RandomAccessIterator,一般指向开头和结尾。第三个参数为比较函数,注意返回值是要设计为bool型或者能转换为bool型。注意这里匿名函数的写法。api里说了第三个参数可以为函数或者对象。
accumulate函数的api。注意匿名函数里的string &r意思是新建一个空的string的对象。

另外一个版本,也是C++最快版本:

bool compare(string l, string r)
{
    return l+r > r+l;
}

class Solution {
public:
    string largestNumber(vector<int>& nums) {

        vector<string> p;
        for (int i = 0; i < nums.size(); i++)
            p.push_back(to_string(nums[i]));
        
        sort(p.begin(), p.end(), compare);
        
        string res;
        for (int i = 0; i < p.size(); i++){
            if (p[i] == "0" && res == "0") continue;
            else res += p[i];
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/anlian523/article/details/83114187
今日推荐