我已经理解compare
函数正在对值进行排序,以便按递减顺序显示数字组合。
例如:给定[3, 30, 34, 5, 9]
,最大的数字是9534330
。
int compare(const void *a1,const void *b1){
int a = *(int*)a1;
int b = *(int*)b1;
int i=0;
char arr[10000]={0};
char brr[10000]={0};
sprintf(arr, "%d%d", a, b);
sprintf(brr, "%d%d", b, a);
int k = strlen(arr);
for(i=0; i < k; i++){
if(arr[i] != brr[i])
return brr[i] - arr[i];
}
return b-a;
}
char* largestNumber(const int* A, int n1) {
char *ans = (char*) calloc(10000000,sizeof(char));
int i=0, count=0;
qsort(A, n1, sizeof(int), compare);
if(A[0] == 0){
ans[0] = '0'; ans[1]=0; return ans;
}
for(i=0; i<n1; i++){
int k = A[i];
// printf("%d ", k);
count += sprintf(ans+count, "%d", k);
}
// printf("\n");
ans[count] = 0;
return ans;
}
我的怀疑如下:
这段代码如何运作?
for(i=0; i < k; i++){
if(arr[i] != brr[i])
return brr[i] - arr[i];
}
它正在比较arr
和brr
的内容,但是如何返回值以便以这种方式对值进行排序?
即使它返回值,也应按递增顺序打印。为什么它按降序显示?
答案 0 :(得分:0)
这个比较功能很奇怪
要了解其工作原理,让我们开始考虑what qsort expects:它需要一个接受2个数字的函数,a
和b
,以及
如果第一个参数被认为分别小于,等于或大于第二个参数,则返回小于,等于或大于0的整数。
在这种情况下,正如我们将看到的,它实际上返回相反的结果,即,如果考虑 second 参数,它返回小于,等于或大于0的整数分别小于,等于或大于第一。这只是因为此代码的作者希望按降序排序而不是按升序排序。
那就是说,这个比较功能是一个特殊的功能:让我们看看它的作用。虽然它适用于数字(它接受void*
,这是一个通用指针,但它然后将两个参数都转换为int*
并取消引用它们),它不会在数字上对它们进行比较,甚至不能在数字上进行比较经典的字母数字方式。
相反,它指示一旦转换为字符串,两个数字的顺序必须连接起来以生成数字序列,这些数字被解释为数字,产生最大可能结果(这是由另一个函数的名称暗示的) ,largestNumber
)。它通过指示必须首先采用的最大数字来实现。这听起来很复杂,但有些例子会澄清。
让我们取数字3和4.如果你把它们当作字符串("3"
和"4"
),你可以用两个不同的顺序连接它们,得到"34"
或{{1 }}。现在,将这些字符串转换回数字:哪一个更大?显然,34&lt; 43,如果你想要最大的数字(43),你必须把4作为第一个数字,3作为第二个。在这种情况下,函数将告诉您最大数字是4.它通过返回一个正数(在这种情况下为1)来实现。
我们取而代之的是30和4。如果您连接它们,则会得到"43"
或"304"
。从304&lt; 430,该函数告诉你最大数是4.因此,从这个观点来看,4> 30,这是数字排序的反面。
如果你选择3和30,那么两个可能的连接是"430"
和"330"
,并且因为330&gt; 303你必须先拿3,该功能告诉你3&gt; 30.同样,它与数字排序相反。
如果您选择30和30,则必须在"303"
和"3030"
之间进行选择,它们是相同的,在这种情况下,函数返回0.
现在是一个棘手的案例:如果比较3和33,两个“字符串化”数字是相同的("3030"
和"333"
),所以我们期望0.实际上在这种情况下函数告诉你最大的数字是第二个...但是没关系,因为结果是相同的。
这种比较究竟如何运作?首先,使用"333"
将数字转换为字符串。考虑到2个字符串(让我们称之为sprintf
和"ab"
)必须具有相同的长度,因此它使用"ba"
检查一个字符串的长度,然后循环检查每个数字,开始从第一个。如果strlen
和ab
之间的数字相同,则它什么都不做,只是转到下一个;如果它不同,则比较它们并返回ba
的数字减去brr
的数字。例如,当比较3和30时,arr
将包含330和arr
303.在第一次迭代(当brr
时)它将检查第一个数字:两者都是3,所以你不能选择哪个数字更高。移至第二位:3&gt; 0,所以i==0
&gt; arr
,因此该函数必须返回一个负数,事实确实如此:它返回brr
。
因此,该函数会比较0 - 3 = -3
和a
并返回:
此表显示了经典数字排序,经典字母数字排序和此自定义排序(我称之为“最大字符串数字排序”)的结果
b
至于为什么它们按递减顺序打印,只是因为这一行:
a b Numeric sort Alphanumeric sort Largest stringified number sort
3 4 3 < 4 3 < 4 34 < 43 --> return 1 > 0 --> 3 < 4
30 4 30 > 4 30 < 4 304 < 430 --> return 1 > 0 --> 30 < 4
3 30 3 < 30 3 < 30 330 > 303 --> return -3 < 0 --> 3 > 30
3 31 3 < 31 3 < 31 331 > 313 --> return -2 < 0 --> 3 > 31
3 32 3 < 32 3 < 32 332 > 323 --> return -1 < 0 --> 3 > 32
3 33 3 < 33 3 < 33 333 == 333 --> return 30 > 0 --> 3 < 33
3 34 3 < 34 3 < 34 334 < 343 --> return 1 > 0 --> 3 < 34
30 30 30 == 30 30 == 30 3030 == 3030 --> return 0 == 0 --> 30 == 30
如果您想按升序查看它们,请将其更改为:
return brr[i] - arr[i];