字符串 放进一个数组_剑指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;

}

1.栈和队列的共同特点是(只允许在端点处插入和删除元素) 4.栈通常采用的两种存储结构是(线性存储结构和链表存储结构) 5.下列关于栈的叙述正确的是(D) A.栈是非线性结构B.栈是一种树状结构C.栈具有先进先出的特征D.栈有后进先出的特征 6.链表不具有的特点是(B)A.不必事先估计存储空间 B.可随机访问任一元素 C.插入删除不需要移动元素 D.所需空间与线性表长度正比 7.用链表表示线性表的优点是(便于插入和删除操作) 8.在单链表中,增加头结点的目的是(方便运算的实现) 9.循环链表的主要优点是(从表中任一结点出发都能访问到整个链表) 10.线性表L=(a1,a2,a3,……ai,……an),下列说法正确的是(D) A.每个元素都有一个直接前件和直接后件 B.线性表中至少要有一个元素 C.表中诸元素的排列顺序必须是由小到大或由大到小 D.除第一个和最后一个元素外,其余每个元素都有一个且只有一个直接前件和直接后件 11.线性表若采用链式存储结构时,要求内存中可用存储单元的地址(D) A.必须是连续的 B.部分地址必须是连续的C.一定是不连续的 D.连续不连续都可以 12.线性表的顺序存储结构和线性表的链式存储结构分别是(随机存取的存储结构、顺序存取的存储结构) 13.树是结点的集合,它的根结点目是(有且只有1) 14.在深度为5的满二叉树中,叶子结点的个为(31) 15.具有3个结点的二叉树有(5种形态) 16.设一棵二叉树中有3个叶子结点,有8个度为1的结点,则该二叉树中总的结点为(13) 17.已知二叉树后序遍历序列是dabec,中序遍历序列是debac,它的前序遍历序列是(cedba) 18.已知一棵二叉树前序遍历和中序遍历分别为ABDEGCFH和DBGEACHF,则该二叉树的后序遍历为(DGEBHFCA) 19.若某二叉树的前序遍历访问顺序是abdgcefh,中序遍历访问顺序是dgbaechf,则其后序遍历的结点访问顺序是(gdbehfca) 20.据库保护分为:安全性控制、 完整性控制 、并发性控制和据的恢复。 1. 在计算机中,算法是指(解题方案的准确而完整的描述) 2.在下列选项中,哪个不是一个算法一般应该具有的基本特征(无穷性) 说明:算法的四个基本特征是:可行性、确定性、有穷性和拥有足够的情报。 3. 算法一般都可以用哪几种控制结构组合而(顺序、选择、循环) 4.算法的时间复杂度是指(算法执行过程中所需要的基本运算次) 5. 算法的空间复杂度是指(执行过程中所需要的存储空间) 6. 算法分析的目的是(分析算法的效率以求改进) ............ .................
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值