字符串 放进一个数组_剑指offer_45.把数组排成最小的数

4685a1168e43b60dcf3817d32987816a.png

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

//题目:

/*

输入一个正整数数组,把数组里所有数字拼接起来,排成一个数,打印能拼接处的所有数字中最小的一个。

例如,输入数组{3,32,321},则打印出这3个数字能排成的最小数字321323.

*/

/*

思路:

首先对于这种题目,单独一个int类型的数字不会溢出,但是几个int类型拼接起来之后,可能会导致用int类型表示溢出。

因此这种问题属于大数问题,对于大数问题,我们一般的解决思路是通过将数字转换为字符串。因为拼接之后的所有数字的位数是一样的,

因此我们可以通过字符串大小的比较规则进行比较即可。(字符串大小的比较规则:字符串对应的ASCII码)

暴力法:

直接将数组中所有数字进行排列组合,对于一个长度为n的数组,其排列组合的种类有n!中,然后分别进行比较。

因此时间复杂度是O(n!)

优化方法:

1.为解决大数问题,将数组中的整型数字转化为字符串

2.比较两两个数字之间的先后顺序,谁排在前面更小,从而对数组进行排序

3.建立自己的排序规则(对于整型数组{m,n},如果字符串 mn < nm,那么我们定义m < n;如果字符串 mn > nm,那么我们定义m > n;如果字符串 mn = nm,那么我们定义m = n;)

4.两个数字先后顺序的比较方法:两个数字连接,比较两种连接方式得到的字符串哪个大。

*/

#pragma warning(disable : 4996)

#include<iostream>

#include<string>

#include<algorithm>

#include"cstdio"

int compare(const void*strNumber1, const void*strNumber2);

//int型整数用十进制表示最多只有10位(int型占4个字节,每个字节对应8位二进制数,最大值的位数位2^31,一共有10位)

const int g_MaxNumberLength = 10;

//定义两两字符串拼接之后,字符串数组的长度 = 每个整型十进制数对应的最长位数(10) * 2(两个) + 1(“0”字符串结束符)

char*g_StrCombine1 = new char[g_MaxNumberLength * 2 + 1];

char*g_StrCombine2 = new char[g_MaxNumberLength * 2 + 1];

void PrintMinNumber(const int*numbers, int length)

{

if (numbers == nullptr || length <= 0)

return;

//===================将整型数组转化为字符串数组=====================================

char**StrNumbers = (char**)(new int[length]);//初始化一个字符串数组,其中的元素也是字符串,也相当于一个数组,所以要用指针的指针

for (int i = 0; i < length; ++i)

{

StrNumbers[i] = new char[g_MaxNumberLength + 1];//将一个整型数字的十进制表示转换为字符串,除去十进制位数10,要加上一位结束符"0";

//初始化字符串数组的每个元素(每个元素也是一个字符串,也相当于一个数字组)

/*

函数原型:int sprintf(char *buffer, const char *format, [argument]...)

参数:

(1)buffer:是char类型的指针,指向写入的字符串指针;

(2)format:格式化字符串,即在程序中想要的格式;

(3)argument:可选参数,可以为任意类型的数据;

*/

sprintf(StrNumbers[i], "%d", numbers[i]);

}

//=======================将字符串数组进行升序排列================================

/*

void qsort(

void *base,

size_t nmemb,

size_t size,

int (*compar)(const void *, const void *)

);

函数功能:qsort()函数的功能是对数组进行排序,数组有nmemb个元素,每个元素大小为size。

参数base - base指向数组的起始地址,通常该位置传入的是一个数组名

参数nmemb - nmemb表示该数组的元素个数

参数size - size表示该数组中每个元素的大小(字节数)

参数(*compar)(const void *, const void *) - 此为指向比较函数的函数指针,决定了排序的顺序。

如果compar返回值小于0(< 0),降序排列

如果compar返回值等于0(= 0),顺序不确定

如果compar返回值大于0(> 0),升序排列

*/

qsort(StrNumbers, length, sizeof(char*), compare);

//===========================打印升序排序好的字符串数组================================================

for (int i = 0; i < length; ++i)

{

printf("%s", StrNumbers[i]);

}

printf("n");

//==========================释放创建在堆区的字符串数组===========================================

for (int i = 0; i < length; ++i)

delete[]StrNumbers[i];

delete[]StrNumbers;

}

//如果[StrNumber1][StrNumber2] > [StrNumber2][StrNumber1],返回值大于0

//如果[StrNumber1][StrNumber2] < [StrNumber2][StrNumber1],返回值小于0

//如果[StrNumber1][StrNumber2] = [StrNumber2][StrNumber1],返回值等于0

int compare(const void*strNumber1,const void* strNumber2)

{

//[StrNumber1][StrNumber2]

//拼接字符串,通过STL中的strcpy(目标数组,要复制的字符串)

strcpy(g_StrCombine1, *(char**)strNumber1);

strcpy(g_StrCombine1, *(char**)strNumber2);

//[StrNumber2][StrNumber1]

strcpy(g_StrCombine2, *(char**)strNumber2);

strcpy(g_StrCombine2, *(char**)strNumber1);

return strcmp(g_StrCombine1, g_StrCombine2); //字符串比较函数strcmp(字符串1,字符串2),如果1 > 2,则返回值大于0;如果1 < 2,则返回值小于0;

}

//==========================================测试代码==============================

void Test(const char*testName, int*numbers, int length, const char*expectedResult)

{

if (testName != nullptr)

printf("%s begins:n", testName);

if (expectedResult != nullptr)

printf("Expected result is: t%sn", expectedResult);

printf("Actual result is:t");

PrintMinNumber(numbers, length);

printf("n");

}

void Test01()

{

int numbers[] = {3,5,1,4,2};

Test("Test01", numbers, sizeof(numbers) / sizeof(int), "12345");

}

void Test02()

{

int numbers[] = { 3,32,321 };

Test("Test02", numbers, sizeof(numbers) / sizeof(int), "321323");

}

int main()

{

Test01();

//Test02();

system("pause");

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值