数字拆分,最小和的奥秘

本篇博客会讲解力扣“2160. 拆分数位后四位数字的最小和”的解题思路,这是题目链接。先来审题:
数字拆分,最小和的奥秘_第1张图片

先说结论,再来证明。

结论是,按以下步骤操作,可以得到最小和:

  1. 取出该四位数的每一位,存放到数组中。
  2. 把数组按升序排列。
  3. 最小和=2个较小数的和×10+2个较大数的和。

比如:对于四位数2932,先取出每一位并升序排列得到2239,则最小和为:(2+2)×10+3+9=52。

证明:把一个四位数拆分成2个数,可以拆分成2个两位数,也可以拆分成1个三位数和1个一位数。要使得和最小,必须拆分成2个两位数。

为什么呢?如果拆分成1个三位数和1个一位数,则把位数较多的那个数的最高位放到位数较少的数的最高位,能使得两数之和变小。比如329和2,若改成29和32,则和变小了。这又是为什么呢?这是因为,改变之前,3的作用是300,改变之后,3的作用是30。

好,既然要拆分成2个两位数,那就要两两一组。为了使得每个数都要尽可能的小,我们让较小的a和b放到高位,较大的c和d放到低位,组成ac和bd,或者ad和bc,此时两数之和为(a+b)×10+c+d,证毕。

写成代码就非常简单了。拆分时采取“模10除10法”,即先mod10取出最后一位,再除10去掉这一位,直到该数变成0。至于排序,可以调用C语言的库函数qsort,不会使用这个函数的朋友可以戳这里。

代码如下:

int CmpInt(const void* p1, const void* p2)
{
    return *(int*)p1 - *(int*)p2;
}

int minimumSum(int num){
    // 取出四位数的每一位,存在数组中
    int a[4] = {0};
    for (int i = 0; i < 4; ++i)
    {
        a[i] = num % 10;
        num /= 10;
    }

    // 把数组排成升序
    qsort(a, 4, sizeof(int), CmpInt);

    // 大的数放低位,小的数放高位,和最小
    return (a[0] + a[1]) * 10 + a[2] + a[3];
}

数字拆分,最小和的奥秘_第2张图片
通过喽。

总结

本题的难点在于如何拆分,即拆分成2个两位数,分别是ac和bd,或者ad和bc,其中abcd都是原来四位数的某一位,而a和b是2个较小的数,c和d是2个较大的数。

感谢大家的阅读!

你可能感兴趣的:(力扣刷题,算法,数据结构,c语言,leetcode,力扣)