力扣179. 最大数----字符串处理+排序

179. 最大数

给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。

注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。

示例 1:

输入:nums = [10,2]
输出:"210"
示例 2:

输入:nums = [3,30,34,5,9]
输出:"9534330"
示例 3:

输入:nums = [1]
输出:"1"
示例 4:

输入:nums = [10]
输出:"10"
 

提示:

1 <= nums.length <= 100
0 <= nums[i] <= 109

题解:

首先最直观的想法便是排序求解,即我们若能将所有的数字按照我们想要的顺序排放的话即可解题成功。此题关键就在于我们如何完成排序。
首先需要明白关于排序的问题对于C语言来说首先应该想到qsort函数,因为它可以自己定义我们要按照什么来排序,因此我们使用qsort函数自行定义排序原则即可。

比如对于13和17,我们应该将谁放前面谁放后面的呢?
我们可以这样考虑,若我们能把每个数字的最高位提取出来,然后进行比较,若没有比较出结果,则继续抽取第二高位数字进行比较,如此比较直到没有位可以比了,这时候我们即可得到想要的结果。
但这种方法实现起来较为复杂,复杂度较高,因此我们可以采用下面的思路:
即对于13和17,我们开始不知道应该把谁放在前面,谁放在后面。我们可以将二者可能的组合方式都组合看看,比较一下组合后的结果,再根据此结果完成我们想要的排序。

所谓“组合比较”的精髓就在于cmp函数里的两个while循环。

C代码:

long cmp(int*x,int*y)//因为返回的数很大所有用long接收
{
    long count1 = 10;//因为其可能会很大,用long防止越界
    long count2 = 10;//初始为10,是因为将两个数字拼接最小也为两位数
    while(count1<=*x)
    {
        count1*=10;//得到每个数字对应的倍数
    }
    while(count2<=*y)
    {
        count2*=10;
    }
    return ((*y)*count1+(*x)) - ((*x)*count2+(*y));//交叉相乘
//刚好若x为两位数,则count1为100,因此不论y为多少其乘100后后面两位都是刚好留给x的,
//即每个数的相对大小都没有改变,实现了“拼接”操作
}
char * largestNumber(int* nums, int numsSize){
    qsort(nums,numsSize,sizeof(int),cmp);
    char*res = (char*)malloc(sizeof(char)*(1000));
    //这里不能sizeof(char)*numssize,因为可能会越界,因为nums数组里的每一个数都可能是1位数以上的
    if(nums[0]==0)
    {
        res[0]='0';
        res[1]='\0';
        return res;
    }

    char*p = res;//定义一个指向该动态数组的指针,便于下面的查找
    for(int i=0;i<numsSize;i++)
    {
        sprintf(p,"%d",nums[i]);//将数字变成字符串借助p指针输入res中
        p = p+strlen(p);
//由于每次输入的位置不会自己移动,如果不加p的话每次sprintf都会进行同位置的覆盖,
//所以需要借助指针p来完成移动的操作,注意strlen(p)其只会计算已经被赋值的长度。
//p+1代表访问第二个元素,不管是int型数组还是char型数组都是这样的,其与字节无关。
    }
    return res;
}

Java代码:

class Solution {
    public String largestNumber(int[] nums) {
        int len = nums.length;
        String[] arr = new String[len];
        for (int i = 0; i < len; i++){
            arr[i] = Integer.toString(nums[i]);
        }
        Arrays.sort(arr, new StringCompare());
        if (arr[0].equals("0")){
            return "0";
        }
        StringBuilder ans = new StringBuilder();
        for (String elem : arr){
            ans.append(elem);
        }
        return ans.toString();
    }
}

class StringCompare implements Comparator<String>{
    public int compare(String le, String ri){
        int len1 = le.length(), len2 = ri.length();
        for (int i = 0; i < len1 + len2; i++){
            if (le.charAt(i % len1) > ri.charAt(i % len2)){
                return -1;
            }
            else if (le.charAt(i % len1) < ri.charAt(i % len2)){
                return 1;
            }
        }
        return 0;
    }
}

另外我们也可以不用p指针来完成移动的操作,这时候就需要一个函数strcat实现。

long cmp(int*x,int*y)
{
    long count1 = 10;
    long count2 = 10;
    while(count1<=*x)
    {
        count1*=10;
    }
    while(count2<=*y)
    {
        count2*=10;
    }
    return ((*y)*count1+(*x)) - ((*x)*count2+(*y));
}
char * largestNumber(int* nums, int numsSize){
    qsort(nums,numsSize,sizeof(int),cmp);
    char*res = (char*)malloc(sizeof(char)*(1000));
    memset(res,'\0',1000);
    if(nums[0]==0)
    {
        
        res[0]='0';
        res[1]='\0';
        return res;
    }

    for(int i=0;i<numsSize;i++)
    {
        char str[100];//需要定义一个小的字符串数组来接收每次数字格式化后的字符串
        sprintf(str,"%d",nums[i]);
        strcat(res,str);//连接
    }
    return res;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向光.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值