arrays - 由数组形成的最大数字(理解解决方案)

标签 arrays algorithm sorting quicksort

编写一个函数,在给定一个非负整数列表的情况下,对它们进行排列,使它们形成尽可能大的数字。例如,给定 [0, 1, 2, 3],形成的最大数字是 3210。

我理解的逻辑:

我们比较两个数字 XY(Y 附加在 X 末尾)和 YX(X 附加在 Y 末尾)。如果 XY 较大,则输出中 X 应位于 Y 之前,否则 Y 应位于之前。例如,设 X 和 Y 分别为 542 和 60。为了比较 X 和 Y,我们比较 54260 和 60542。由于 60542 大于 54260,所以我们将 Y 放在前面。我也可以为此编写代码。

令我惊讶的是这个解决方案:

#include <stdio.h>
#include<stdlib.h>

int swap(const void *c, const void *d) {
    int n1 = *(int*)c;
    int n2 = *(int*)d;

    int a = pow(10, floor(log10(n2)) + 1) * n1 + n2;
    int b = pow(10, floor(log10(n1)) + 1) * n2 + n1;

    if (n1 == 0) return 1;
    if (a < b) return 1;

    return 0;
}

int main() {
    int t = 0, tc = 0;

    scanf("%d", &t);
    for(tc = 1; tc <= t; tc++) {
        int n;
        scanf("%d",&n);
        int arr[n];

        for (int i = 0; i < n; i++) {
            scanf("%d", &arr[i]);
        }

        qsort(arr, n, sizeof(int), swap);

        for (int i = 0; i < n; i++)
            printf("%d", arr[i]);
        printf("\n");
    }
    return 0;
}

令我惊讶的是,它通过了所有测试用例。谁能给我解释一下这个逻辑吗?

最佳答案

这正是您所描述的:

int a = pow(10, floor(log10(n2)) + 1) * n1 + n2;
int b = pow(10, floor(log10(n1)) + 1) * n2 + n1;

如果我们传入XY,那么a就是XY,而 bYX

如果您要连接 2 和 34,则需要将 2 乘以 100(得到 200),然后加上 34(得到 234)。这100是从哪里来的?它是 10 的 34 位数次方。为了获得位数,我们计算 34 以 10 为底的对数并将其向上舍入。

所以:

log10(34) ~= 1.5
floor(log10(34)) == 1
floor(log10(34)) + 1 == 2

10^2 = 100,所以现在我们知道在添加第二个数字之前将第一个数字乘以什么。

第二行以相反的顺序对变量执行相同的操作(计算连接的 YX)。

最后,如果 a < b,我们返回 1,否则返回 0。这使其成为排序函数的工作比较器:

if (a < b) return 1;

编辑

我不确定这条线在做什么:

if (n1 == 0) return 1;

我认为它可能会保护我们免受 log10(0) 结果的影响。 (我不确定返回什么......数学结果是负无穷大。)

基本上,比较器中的结果是“如果 n1 为 0,则将 n2 首先放置”,这总是正确的。 (我只是不是 100% 确定为什么需要它。)

关于arrays - 由数组形成的最大数字(理解解决方案),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45784421/

相关文章:

javascript - 如何在 Rhino 中创建 'real' JavaScript 数组

javascript - 关联数组 Internet Explorer 8/9

algorithm - 如何通过反转子序列对排列进行排序(取自 Skiena 第 3 版)

sorting - 按行长度和字母顺序一次对字符串数组进行排序

php - PHP 中的计数排序

c++ - 异或和移位数组中的位

javascript - 如何有效地比较具有不同键但可能匹配值的2个对象?

c# - 为什么我的字符串在凯撒密码期间发生变化?

algorithm - 有没有比Dijkstra算法更好的以事故总数为参数的最短安全路径算法?

android - react-native-camera中YUV_420_888格式的算法旋转