把数组排成最小的数

本文介绍了一种特殊的排序算法,用于将整数数组排列成最小可能的数值。通过将整数转换为字符串并比较拼接后的结果,实现了自定义的比较规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

排序的另一种phase,不是按照大小或者是字典序的顺序进行排序,而是根据题目实际的要求进行cmp函数的设计,达到题目的要求

该问题就是把(字符)数组进行排序,结果是:所有的字符连接起来形成一个最小的数字。

既然是字符的连接,那么相邻的两个数组元素就是进行连接然后进行题目要求的比较(这里是连接后,所形成的字符串转换成书之后的大小比较)。


【题  目】输入一个正整数数组,将他们连接起来排成一个数,输出所有排出的数字中最小的一个。例如:输入数组『32,321』,输出所能排出的最小数为:32132.请给出该问题的算法。

  【思  路】我们希望能够找到一种规则,按照这种规则排列出来的数是最小的数。要确定排序的规则,我们就必须知道,对于任意两个正整数a和b,如果确定一个规则,使得按照该问题进行排序能得到最小的数,也就是要比较a和b的值,而这种比较不是普通的数值的大小。

  对于数字a和b,排列的结果为ab和ba,如果ab小于ba,应该输出ab,即a排在b的前面,也就是a<b。反之,如果ba小于ab,即b排在a前面,也就是b<a。如果ab等于ba,那么a=b。

  接下里的问题是:给出数字a和b,如果拼接得到ab或者ba,然后比较他们的大小?如果直接用数值进行拼接当然是可以的,但是我们考虑到a和b都是int型的,如果拼接后得到数字超出int型的范围导致结果溢出该怎么办?很自然我们想到可以现将整数都转换成字符串类型,然后在连接。

  如何比较ab和ba的大小?很显然按字典序直接比较ab字符串和ba字符串的值就可以了。根据这个思路,我们可以写出如下的代码:

复制代码
 1 #include<iostream>
 2 #include<string>
 3 #include<cstring>
 4 #include<cstdlib>
 5 using namespace std;
 6 
 7 //每个整数最长有10个数字组成;
 8 const int maxDigits = 10;
 9 
10 //两个临时字符串用于存放ab和ba
11 char* strCombine1 = new char[2*maxDigits+1];
12 char* strCombine2 = new char[2*maxDigits+1];
13 
14 //定义a和b的比较规则;
15 //定义如果ab<ba,则a<b;
16 //定义如果ba<ab,则b<a;
17 //定义如果ab=ba,则a=b;
18 int comp(const void* a,const void* b)
19 {
20     //得到ab
21     strcpy(strCombine1,*(const char**)a);
22     strcat(strCombine1,*(const char**)b);
23     
24     //得到ba
25     strcpy(strCombine2,*(const char**)b);
26     strcat(strCombine2,*(const char**)a);
27 
28     return strcmp(strCombine1,strCombine2);
29 }
30 
31 void printMinNumber(int numbers[],int length)
32 {
33     if(numbers == NULL || length < 0)
34         return;
35 
36     //建立新的字符串数组
37     char **strNumbers = (char**)(new int[length]);
38 
39     //每个字符串数组的元素建立新的字符串,并复制为numbers中的值
40     for(int i = 0;i < length;++i)
41     {
42         strNumbers[i] = new char[maxDigits + 1];
43         sprintf(strNumbers[i],"%d",numbers[i]);
44     }
45 
46     //按照定义的规则进行快速排序
47     qsort(strNumbers,length,sizeof(char*),comp);
48 
49     //输出结果
50     for(i = 0;i < length;++i)
51     {
52         printf("%s",strNumbers[i]);
53     }
54     printf("\n");
55 
56     //delete
57     for(i = 0;i < length;++i)
58     {
59         delete[] strNumbers[i];
60     }
61     //delete
62     delete[] strNumbers;
63 }
64 
65 int main()
66 {
67     cout<<"Please Enter your arraylenth:"<<endl;
68     int n =0;
69     cin>>n;
70 
71     cout<<"please Enter your array elements:"<<endl;
72     int* array = new int[n];
73     for(int k =0;k < n;++k)
74     {
75         cin>>array[k];
76     }
77 
78     cout<<"the minNumber from your array is:"<<endl;
79     printMinNumber(array,n);
80 
81     delete[] array;
82     return 0;
83 }
复制代码

  运行结果如下:

  其实该问题还有一问,是要求证明该算法是正确的,笔者窃以为对于我们找出的排序规则来说这是显然的。这就好比如果我们定义了比较两个数大小的规则,比如就是最简单的数值比较规则,然后有一个数组,要按照这个比较规则进行排序,它排出来的序是违反这个规则的?显然是不可能的。所以只需确定这个比较的规则是正确的就可以了,而比较规则的正确性,这里是借助字符串的比较规则来实现的,完全没有问题。所以个人感觉这个证明是不必要的。当然如果对这个说法有疑问,要看证明过程,请移步这里


 

References:  

程序员面试题精选100题:http://zhedahht.blog.163.com/blog/static/25411174200952174133707/

注:

1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。

2)博主python27对本博客文章享有版权,网络转载请注明出处http://www.cnblogs.com/python27/。对解题思路有任何建议,欢迎在评论中告知。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值