数串

1. 题目描述
设有n个正整数,将他们连接成一排,组成一个最大的多位整数。
如:n=3时,3个整数13,312,343,连成的最大整数为34331213。
如:n=4时,4个整数7,13,4,246连接成的最大整数为7424613。
2. 输入描述
有多组测试样例,每组测试样例包含两行,第一行为一个整数N(N<=100),第二行包含N个数(每个数不超过1000,空格分开)。
3. 输出描述
每组数据输出一个表示最大的整数。

测试用例 举例:

/**
testcase:
2
12 123
output:
12312

4
7 13 4 246
output:
7424613


37
93 672 946 153 947 82 522 772 725 413 936 649 399 123 821 93 29 860 572 344 608 590 554 210 115 307 313 535 636 184 291 66 178 379 204 523 758
output:
9479469393936860828217727587256726664963660859057255453552352241339937934431330729291210204184178153123115


62
135 518 476 936 415 616 663 496 968 206 604 398 169 983 277 634 453 280 215 380 239 465 649 4 609 501 875 549 712 90 226 822 740 860 885 377 740 746 825 864 578 636 31 70 880 764 415 475 446 490 744 394 640 451 378 873 911 205 572 672 360 516
output:
9839689369119088588087587386486082582276474674474074071270672663649640636634616609604578572549518516501496490476475465453451446441541539839438037837736031280277239226215206205169135

*/

分析:
很容易想到贪心的策略,将高位大的元素放置在前面最后生成的数更大,当最高位的数一致的时候,考虑次高位,按照类似与字典序的顺序依次拼接输入的数组。但是存在一个问题是,如果一个数是另外一个数的前缀的时候如何判断两个数的顺序呢?比如对于12和123,很显然12123比12312小,这时长数应排在短数前面,但是对于96和961来说,96961比96196大,这时短数应排在长数前面。因此不能直接按照字典序的顺序决定,需要将短的字符循环扩展成长字符串一样的长度,如123和12需要扩展成比较123和121、96和961需要扩展为969和961, 9和961扩展为999和961。
一种较为简单的做法是将输入的元素作为字符串进行处理,使用字符串的拼接运算和比较函数。直接对比拼接后结果

方法1

#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>

struct MyCmp {
    bool operator()(int a, int b) {
        std::vector<int> sa, sb;
        while (a) {
            sa.push_back(a % 10);
            a /= 10;
        }
        while (b) {
            sb.push_back(b % 10);
            b /= 10;
        }
        std::reverse(sa.begin(), sa.end());
        std::reverse(sb.begin(), sb.end());
        int nLenOfSa = sa.size(), nLenOfSb = sb.size();
        // 循环扩充至相同的长度
        if (nLenOfSa < nLenOfSb) {
            for (int i = nLenOfSa; i < nLenOfSb; ++i)
                sa.push_back(sa[i - nLenOfSa]);
        }
        else if (nLenOfSa > nLenOfSb) {
            for (int i = nLenOfSb; i < nLenOfSa; ++i)
                sb.push_back(sb[i - nLenOfSb]);
        }

        assert(sa.size() == sb.size());

        return sa > sb;
    }
};

class Solution {
public:
    std::string getMaxNum(std::vector<int> &nums) {
        std::sort(nums.begin(), nums.end(), MyCmp());
        std::string res;
        for (auto e: nums) {
            res += std::to_string(e);
        }
        return res;
    }
};

int main() {
    unsigned n;
    std::cin >> n;
    std::vector<int> nums(n);
    for (int i = 0; i < n; ++i)
        std::cin >> nums[i];
    std::cout << Solution().getMaxNum(nums) << std::endl;
    return 0;
}

方法2

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
    unsigned n;
    std::cin >> n;
    std::vector<std::string> vStr(n);
    for (int i = 0; i < n; ++i)
        std::cin >> vStr[i];
    std::sort(vStr.begin(), vStr.end(), [](std::string s1, std::string s2) {
       return (s1 + s2) > (s2 + s1);
    });
    for (auto &e: vStr)
        std::cout << e;
    std::cout << '\n';
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值