将数组排成最小的数

  • 题目:输入一个正整数的数组,将数组中所有数字拼接在一起排列成一个新的数,打印能拼接出来的所有数字中最小的一个,

  • 案例:输入数组{12,4,55},则能打印出最小的数组是:12455

  • 首先还是最简单的做法,我们求出数组中所有数字的全排列,然后将每个排列的情况拼接成一个新的数字,比较得到最小的数字情况。求数组的全排列问题我们在之前的文章:数据结构与算法–字符串的排列组合问题

  • 更具排列组合知识,n个数组共有n!个排列,当数组元素比较多的时候,时间复杂度会是一个非常大的数值,运行会非常慢,应该有更快的方案。

  • 常规优化:穷举法是为了避开了一个选择交换的过程,如果只有两个元素,我们找出小的放到前面,那这个题目就转成了一个找数组的排序规则的过程。数组根据这个排序规则排列成一个最小的数字。要确定排序规则,就需要比较两个数字,也就是给出 m,n两个数,我们需要确定一个排序规则判断m,n那个应该在前面,这不是比较数字大小的问题。

  • 根据题目要求,两个数字m,n,能拼出mn,nm两个数字。

    • 如果mn < nm,那么我们应该输出mn,也就是m应该在n前面,我们定义m 小于 n
    • 如果mn > nm,那么我们应该输出nm,也就是n在m前,我们定义n 小于 m
    • 同样mn = nm定义 m= n
    • 以上中 > < = 是我们数学意义上的比较,而大于,小于,等于,是我们自己定义的大小关系。
  • 那么我们接下来需要考虑的是怎么去拼接数字,当给出数字,m,n,我们直接计算的方式得到mn,nm的关系并不难。但是还有一个关键问题,当mn拼接后得到数字无法用int表达的时候,超过int类型的范围那么我们就不能用普通的计算方式。有一个潜在的大数问题让我必须用字符串的方式来计算。

  • 大数问题用字符串解决,字符串的比较问题,因为此处mn, nm 两个数必然是两个长度相等的字符串,那么比较他大小只需要按照字符串的大小比较规则就可以了。

  • 基于以上分析,我们可以先对数组中的所有数组进行快速排序

  • 排序规则用我们自定义规则,

  • 从小到大排序后,将所有数字依次拼接,就得到了最小值。

  • 经如上分析有如下代码:

/*** 将数组中所有数据合并成一个数,求出能排成的最小数** @author liaojiamin* @Date:Created in 12:00 2021/6/8*/
public class FinMinNumber {public static String pringMinNumber(int[] array) {if (array == null || array.length <= 0) {return "";}if (array.length == 1) {return String.valueOf(array[0]);}String[] str = new String[array.length];for (int i = 0; i < array.length; i++) {str[i] = String.valueOf(array[i]);}quickSort(str, 0, str.length - 1);StringBuilder stringBuilder = new StringBuilder();for (String s : str) {System.out.print(s +", ");stringBuilder.append(s);}System.out.println();return stringBuilder.toString();}/*** 快排法,按从小到大排序字符串,字符串大小规则自定义* */public static String[] quickSort(String[] str, Integer left, Integer right) {if (left < right) {Integer temp = quickSortSwap(str, left, right);quickSort(str, left, temp - 1);quickSort(str, temp + 1, right);}return str;}public static Integer quickSortSwap(String str[], Integer left, Integer right) {if (left < right) {String position = str[left];while (left < right){while (left < right && myCompareTO(str[right], position) > 0) {right--;}if (left < right) {str[left] = str[right];left++;}while (left < right && myCompareTO(str[left], position) < 0) {left++;}if (left < right) {str[right] = str[left];right--;}}str[left] = position;}return left;}/*** 字符串大小规则比较,* ab > ba => a>b* ab == ba => a==b* ab<ba =>  a<b* */public static Integer myCompareTO(String a, String b){String ab = a+b;String ba = b+a;return ab.compareTo(ba);}public static void main(String[] args) {int[] str_1 = {12, 34, 1, 34, 777, 33, 99, 86, 56, 9};System.out.println(pringMinNumber(str_1));}
}

后续问题

  • 如上实现方案中有两个问题:

    • 第一我定义了一种新的比较两个数的规则,但是这种规则是我们想出来的,并不是定理或者公
    • 第二我们定义的是比较两个数的规则,但是用它来排序一个包含多个数字的数组,最终得到的是否是我们需要的的最小数字?
  • 那么以上两点我们必须给出严格的数学证明,来确保方案的准确:

  • 第一,证明之前订阅的比较规则有效性。一个比较规则有效,需满足三个条件,自反性,对称性,传递性

    • 自反性: 显然,如果ab = ba, 那么 a等于b
    • 对称性: 如果a 小于 b,则ab < ba, 所以ba > ab,因此b 大于 a
    • 传递性: 如果a 小于 b, 则 ab < ba。 假设a, b都是十进制表示时候,分别有1位,m位,有如下推断
      如果有a 小于b
      ab = a * 10 m + b
      ba = b* 101 + a
      若 ab < ba
      有 a * 10 m + b < b* 101 + a
      a * 10 m - a < b* 101 - b
      a(10m-1) < b(101-1)
      a/(101-1) < b/(10m-1)
      同时如果有b 小于c,则bc < cb,同样假设c十进制n位,与以上证明一致,得到
      b/(10m -1) < c(10n -1)
      综上: a/(101-1) < b/(10m-1) < c(10n -1)
      a/(101-1) < c(10n -1)
      a(10n -1) < c(101-1)
      a * 10n + c < c * 101+a
      ac < ca
      a<c
  • 如上证明了这种比较规则满足自反性,对称性,传递性,是一种有效的比较规则,

  • 以下还需要证明根据如上规则将数组排序后,将数组中所有数字拼接起来得到的确实是最小值。

  • 略(太难了)

上一篇:数据结构与算法-- 数组中出现次数超过一半的数字(时间复杂度的讨论)
下一篇:数据结构与算法–丑数

数据结构与算法--将数组排成最小的数相关推荐

  1. [PHP] 算法-把数组排成最小的数的PHP实现

    输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323.解法1 1.数组排序,使 ...

  2. 算法:把数组排成最小的数

    * @Description 把数组排成最小的数* @问题:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.* 例如输入数组{3,32,321},则打印出这 ...

  3. printf打印数组_(45)C++面试之把数组排成最小的数

    // 面试题45:把数组排成最小的数 // 题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼 // 接出的所有数字中最小的一个.例如输入数组{3, 32, 321},则打印出这3 ...

  4. 【剑指offer-Java版】33把数组排成最小的数

    把数组排成最小的数 难点在于比较规则的确定以及比较规则的正确性证明 比如:仅仅是局部的两个数字的顺序较小,如何保证整个数组按此规则进行排序后达到全局的较小 书中关于这一点的证明直接用的反证法,忘的差不 ...

  5. 33:把数组排成最小的数

    /*** 面试题33:把数组排成最小的数* 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.* 例如输入数组{3,32,321},则打印出这三个数字能排成的 ...

  6. 《剑指offer》-- 把数组排成最小的数、丑数、二进制中1的个数、表示数值的字符串、替换空格

    一.把数组排成最小的数: 1.题目: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为 ...

  7. 【LeetCode】剑指 Offer 45. 把数组排成最小的数

    [LeetCode]剑指 Offer 45. 把数组排成最小的数 文章目录 [LeetCode]剑指 Offer 45. 把数组排成最小的数 package offer;import java.uti ...

  8. 列表转化成数组_30. 把数组排成最小的数

    把数组排成最小的数 题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为3213 ...

  9. 面试题45. 把数组排成最小的数

    题目: 面试题45. 把数组排成最小的数 题解: 1. 题解一: 2. 题解二: * 解题思路:* 先将整型数组转换成String数组,然后将String数组排序,最后将排好序的字符串数组拼接出来.关 ...

最新文章

  1. 机器学习与算法面试太难?
  2. python 将列和索引的值变换_【编辑小组成长日记】Python学习第二期
  3. 俞敏洪:创业者应该避开的10个坑
  4. iOS的相对路径和绝对路径
  5. Pentaho 7.0更新:数据准备和分析两不误
  6. 听说你想从事中间件开发?
  7. AntiSamy测试
  8. 账龄分析表excel模板_优秀财务的Excel水平!
  9. 优化vmware mac神器beamoff
  10. c语言数字类型转字符类型,C语言字符类型和数字类型互相转换
  11. 注册github账号指南
  12. CROSSFORMER: A VERSATILE VISION TRANSFORMER BASED ON CROSS-SCALE ATTENTION
  13. V社线下沙龙·深圳站——12.05(周六)
  14. 今天测试twm000 850的windows7 记录
  15. python尼姆游戏_python实现聪明的尼姆游戏(人机对战)
  16. 目标检测YOLO实战应用案例100讲-基于多尺度特征融合的水下小目标检测方法研究
  17. 英语语音篇 - 特殊发音记录
  18. 动手深度学习——Pytorch 入门语法一
  19. 西安电子科技大学计算机专硕调剂,西安电子科技大学人工智能学院2020研究生调剂通知...
  20. 数学分析 曲面积分与场论初步(第22章)

热门文章

  1. linux c之通过popen执行shell命令
  2. linux网络编程之一般应用采用的协议和不同套接字的地址结构以及用户进程和内核通过哪些函数传递套接字的地址结构
  3. 博图程序需要手动同步_贴吧求助帖博图实例单按钮控制灯的程序
  4. 放寒假的硕博研究生将经历什么?
  5. 你试过不用if撸代码吗?
  6. 闲鱼有微信小程序吗_微信小程序商品展示页面(仿咸鱼)
  7. python统计出现的中文标点_Python处理中文标点符号大集合
  8. html怎么快速打出来的,javascript – 快速打印HTML5画布
  9. 51单片机外部地址c语言,cx51与c语言对单片机内部和外部资源变量和地址的定义是否兼容?为什么...
  10. java接口那一节是哪的知识_Java中的接口知识汇总