1,问题:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
2,想法:
(1),最直接的做法是求出这个数组数字的全排列,然后把每个排列拼起来,求最后最小的值,这种情况需要考虑n!中情况,不好!
(2),另外需要考虑的一个问题是大数问题,因为单个数字不会超过数字表示范围,但排起来后可能会超出数字表示范围,所以最好的办法是用字符串来表示拍起来的数,而最小的数,表示成相应的字符串也是最小的,因为字符串的比较也是按位比较的。
所以我们要做的就是先把整数数组转换成一个字符串数组,然后再把字符串数组按升序排序,这样最后排序完的字符串数组排列起来就是一个最小的数的字符串表示。
3,在vs2008上的代码为:
#include "stdafx.h"
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <iostream>
using namespace std;
const int maxnumberlength = 10;
char* strcombine1 = new char[2*maxnumberlength + 1];//两个字符串合并
char* strcombine2 = new char[2*maxnumberlength + 1];
int cmp(const void *str1, const void *str2)
{
strcpy(strcombine1, *(char **)str1);//还必须这么写,不能直接写(char*) str1;
strcat(strcombine1, *(char **)str2);
strcpy(strcombine2, *(char **)str2);
strcat(strcombine2, *(char **)str1);
return strcmp(strcombine1, strcombine2);
}
void PrintMinNumber(vector<int> numbers)
{
if (numbers.empty())
{
return;
}
int length = numbers.size();
char** strnumbers = new char*[length];
//把整形数组存为另一个字符串数组
for (int i = 0; i < length; i++)
{
strnumbers[i] = new char[maxnumberlength + 1];
sprintf(strnumbers[i], "%d", numbers[i]);
}
//接下来就是排序了
qsort(strnumbers, length, sizeof(char*), cmp);
for (int i = 0; i < length; i++)
{
cout << strnumbers[i];//321323
}
cout << endl;
for (int i = 0; i < length; i++)
{
delete[] strnumbers[i];
}
delete[] strnumbers;
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<int> vec(3);
vec[0] = 3;
vec[1] = 32;
vec[2] = 321;
PrintMinNumber(vec);
system("pause");
return 0;
}
在牛客网上的编码为:
class Solution {
public:
static int cmp(string s1, string s2)//用static声明是因为它要被下边的sort函数调用
{ //而类里边非静态函数的调用需要具体的对象,而static函数属于类本身
string S1 = s1 + s2; //可以直接调用
string S2 = s2 + s1;
//return strcmp(S1, S2);//strcmp参数是字符指针
return S1 < S2;//字符串可以直接比较,这是代表升序
}
string PrintMinNumber(vector<int> numbers) {
string s;
if (numbers.empty())
{
return s;
}
vector<string> str;
string temp;
//把number数组转换成字符串数组放在str中
int length = numbers.size();
for (int i = 0; i < length; i++)
{
stringstream ss;
ss << numbers[i];
ss >> temp;
str.push_back(temp);
ss.clear();
}
//接下来就是对字符串数组进行排序了
sort(str.begin(), str.end(), cmp);
for (int i = 0; i < length; i++)
{
s += str[i];
}
return s;
}
};
在牛客网上编码尽量不要在类里边使用static变量,因为不好初始化,static成员变量,必须要在类外定义,麻烦!
尽量使用库函数和stl容器。
非要用,就把这些变量定义成全局变量。
//全局变量声明
const int maxnumberlength = 10;
char* strcombine1 = new char[2*maxnumberlength + 1];//两个字符串合并
char* strcombine2 = new char[2*maxnumberlength + 1];
class Solution {
public:
static int cmp(const void *str1, const void *str2)
{
strcpy(strcombine1, *(char **)str1);//还必须这么写,不能直接写(char*) str1;
strcat(strcombine1, *(char **)str2);
strcpy(strcombine2, *(char **)str2);
strcat(strcombine2, *(char **)str1);
return strcmp(strcombine1, strcombine2);
}
string PrintMinNumber(vector<int> numbers) {
string s;
if (numbers.empty())
{
return s;
}
int length = numbers.size();
char** strnumbers = new char*[length];
//把整形数组存为另一个字符串数组
for (int i = 0; i < length; i++)
{
strnumbers[i] = new char[maxnumberlength + 1];
sprintf(strnumbers[i], "%d", numbers[i]);
}
//接下来就是排序了
qsort(strnumbers, length, sizeof(char*), cmp);
for (int i = 0; i < length; i++)
{
s += strnumbers[i];//必须用string加char*后才能继续加char*
}
cout << endl;
for (int i = 0; i < length; i++)
{
delete[] strnumbers[i];
}
delete[] strnumbers;
return s;
}
};