题目
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
解题思路
遇到这个题,全排列当然可以做,但是时间复杂度为O(n!)。在这里我们自己定义一个规则,对拼接后的字符串进行比较。
排序规则如下:
若ab > ba 则 a 大于 b,
若ab < ba 则 a 小于 b,
若ab = ba 则 a 等于 b;
根据上述规则,我们需要先将数字转换成字符串再进行比较,因为需要串起来进行比较。比较完之后,按顺序输出即可。
C++实现
class Solution {
public:
string PrintMinNumber(vector<int> numbers) {
int length = numbers.size();
if (length == 0) {
return "";
}
sort(numbers.begin(), numbers.end(), cmp);
string res;
for (int i = 0; i < length; i++) {
res += to_string(numbers[i]);
}
return res;
}
private:
// 升序排序
static bool cmp(int a, int b) {
string A = to_string(a) + to_string(b);
string B = to_string(b) + to_string(a);
return A < B;
}
};
剑指Offer书上实现
class solution
{
public:
const int g_maxnumberlength = 10;
char *g_strcombine1 = new char[g_maxnumberlength * 2 + 1];
char *g_strcombine2 = new char[g_maxnumberlength * 2 + 1];
void printminnumber(int *numbers, int length)
{
if (!numbers || !length)
return;
char **strnumbers = (char**)(new int[length]); //char** strnumbers = new char*[前面一维数组的长度]
for (int i = 0; i < length; ++i)
{
strnumbers[i] = new char[g_maxnumberlength + 1];
sprintf(strnumbers[i], "%d", numbers[i]);
}
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;
}
private:
int compare(const void *strnumber1, const void * strnumber2)
{
strcpy(g_strcombine1, *(const char**)strnumber1);
strcat(g_strcombine1, *(const char**)strnumber2);
strcpy(g_strcombine2, *(const char**)strnumber2);
strcat(g_strcombine2, *(const char**)strnumber1);
return strcmp(g_strcombine1, g_strcombine2);
}
};
- 时间复杂度:O(nlogn),和qsort的时间复杂度相同
- 空间复杂度:O(1)