【编程题目】把数组排成最小的数

68.把数组排成最小的数(数组、算法)。
题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个。
例如输入数组{32, 321},则输出这两个能排成的最小数字 32132。
请给出解决问题的算法,并证明该算法。

思路:首先,肯定要考虑溢出问题。开始想用字符串,后来改为了用list。思路是先把第一个数字放入list,然后依次把后面的数字插入到合适的位置。

关键问题就是如何判断两个数字哪一个在前面。

①对于 353 、412这样的情况,肯定是第一个数字小的在前面

②遇到数字相同的就比较下一个数字

③那像 3、 32 这样的情况,两个数字前面相同后面不一样长的  把长的数字去掉相同的部分再跟短的数字比

如 3 、3332

3、332

3、32

3、2 后面的数字放前面

再如 321321321、321

321321、321

321、321 相等 哪个放在前面都一样

为了获取数字的每一位方便,有定义了一个结构,存放每个数字各个位上的数,以及位数的大小。整体代码如下:

/*
68.把数组排成最小的数(数组、算法)。
题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个。
例如输入数组{32,   321},则输出这两个能排成的最小数字 32132。
请给出解决问题的算法,并证明该算法。
start to code = 18:42
end time = 19:47
*/

#include <iostream>
#include <list>
using namespace std;

typedef struct SeperateNum
{
    int num[30]; //在前面的是低位
    int len;
}SeperateNum;

SeperateNum getSeperateNum(int n)
{
    SeperateNum s;
    s.len = 0;
    int t = n;
    while(t != 0)
    {
        s.num[s.len++] = t % 10;
        t = t / 10;
    }
    if (s.len == 0) //只有一个数字0的情况
    {
        s.num[0] = 0;
        s.len = 1;
    }
    return s;
}

bool isBefore(SeperateNum a, int na, SeperateNum b, int nb) //a 是否应该放在 b前面 n为当前判断第几个数字
{
    if (b.len - nb < 0 && a.len - na < 0) //两个数字相等 或者一个数字是另一个数字复制了 n遍 321 321321321哪个放前面都一样
    {
        return true;
    }
    else if (b.len - nb < 0 && a.len - na >= 0) //b数字比较短 且b与a的前面都相等
    {
        return isBefore(a, na, b, 1);
    }
    else if(b.len - nb >= 0 && a.len - na < 0) //a数字比较短
    {
        return isBefore(a, 1, b, nb);
    }

    if (a.num[a.len - na] > b.num[b.len - nb])
    {
        return false;
    }
    else if (a.num[a.len - na] < b.num[b.len - nb])
    {
        return true;
    }
    else //本位数字相等判断下一位
    {
        return isBefore(a, na + 1, b, nb + 1);
    }
}

void getMinNum(int * in, int len) //输入数组 和 长度
{
    list<SeperateNum> lminNum;
    list<SeperateNum>::iterator it;
    SeperateNum temp = getSeperateNum(in[0]);
    bool isInsert = false;

    lminNum.push_back(temp);
    for (int i = 1; i < len; i++)
    {
        isInsert = false;
        temp = getSeperateNum(in[i]);
        for(it = lminNum.begin(); it != lminNum.end(); it++)
        {
            if (isBefore(temp, 1, *it, 1)) //需要插入
            {
                lminNum.insert(it, temp);
                isInsert = true;
                break;
            }
        }
        if (isInsert == false) //没有在中间插入 插在最后面
        {
            lminNum.push_back(temp);
        }
    }

    cout << "组合成的最小数字是:";
    for(it = lminNum.begin(); it != lminNum.end(); it++) //输出最小的数字 注意判断结束要用 ‘ != ’ 不能用‘ < ’
    {
        for(int i = it->len - 1; i >= 0; i--)
        {
            cout<< it->num[i];
        }
    }
    cout<< endl;
}

int main()
{
    int a[5] = {321, 321321325, 3, 32};
    getMinNum(a, 4);

    return 0;
}

查到了一个讲C++不错的网址http://www.cplusplus.com/reference/list/list/insert/

整整写了100多行,用到了自定义结构、STL、递归各种复杂的东西。用了1个多小时,还不包括思考的时间。

在网上找答案,发现人家的答案都好简洁啊。

http://blog.csdn.net/cxllyg/article/details/7659525 经验证这里的答案正确 里面还附有证明

方法相当的简单,我怎么就没有想到。 就是把两个数a、b 正反都拼一下 ab、ba 比较一下那个数小就行了。

代码里面直接用了strcmp来做这个。

#include <iostream>
#include <string.h>
using namespace std;

const int g_MaxNumberLength=10;
char* g_StrCombine1=new char[g_MaxNumberLength*2+1];
char* g_StrCombine2=new char[g_MaxNumberLength*2+1];

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);
}

void PrintMinNumber(int *numbers, int length)
{
    if(numbers==NULL || length<=0)
        return;

    char** strNumbers=(char**)(new int[length]);
    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++)
        cout<<strNumbers[i];
    cout<<endl;

    for(int i=0; i<length; i++)
        delete[] strNumbers[i];

    delete[] strNumbers;

}

void main()
{
    int Num;
    cin>>Num;
    int *numbers=new int[Num];
    for(int i=0; i<Num; i++)
        cin>>numbers[i];

    PrintMinNumber(numbers, Num);
    getchar();
}

另一个实现:

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;

bool compare(const string& str1, const string &str2)
{
    string s1=str1+str2;
    string s2=str2+str1;
    return s1<s2;
}

void ComArrayMin(int *pArray, int num)
{
    int i;
    string *pStrArray=new string[num];

    for(i=0; i<num; i++)
    {
        stringstream stream;
        stream<<pArray[i];
        stream>>pStrArray[i];
    }

    sort(pStrArray, pStrArray+num, compare);

    for(i=0; i<num; i++)
        cout<<pStrArray[i];

    cout<<endl;

    delete[] pStrArray;

}

void main()
{
    int Num;
    cin>>Num;
    int *pArray=new int[Num];

    for(int i=0; i<Num; i++)
        cin>>pArray[i];

    ComArrayMin(pArray, Num);

}

【编程题目】把数组排成最小的数,布布扣,bubuko.com

时间: 2024-10-03 02:33:25

【编程题目】把数组排成最小的数的相关文章

编程算法 - 把数组排成最小的数 代码(C)

把数组排成最小的数 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入一个正整数数组, 把数组里所有数字拼接起来排成一个数, 打印能拼接出的所有数字中最小的一个. 大数转换为字符串, 重载快速排序的比较方法, 进行排序, 最后拼接. 代码: /* * main.cpp * * Created on: 2014.6.12 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #include <stdi

剑指OFFER之把数组排成最小的数(九度OJ1504)

题目描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 输入: 输入可能包含多个测试样例.对于每个测试案例,输入的第一行为一个整数m (1<=m <=100)代表输入的正整数的个数.输入的第二行包括m个正整数,其中每个正整数不超过10000000. 输出: 对应每个测试案例,输出m个数字能排成的最小数字. 样例输入: 3 23 13 6 2 23456 56 样

【面试题033】把数组排成最小的数

[面试题033]把数组排成最小的数 题目: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数, 打印能拼接出的所有数字中最小的一个. 例如输入数组{3, 32, 321},则打印出这3个数字能排成的最小数字321323. 思路一: 最直观的想法是求出所有数字的全排列,然后取最小值即可, 根据排列组合的知识,n个数字总共有n!个排列. 思路二: 找到一个排序规则,数组根据这个规则排序之后能排成一个最小的数字. 给出一个规则,判断给出的两个 数字m和n,判断这两个数那个应该排在前面,而不是仅仅

把数组排成最小的数-剑指Offer

把数组排成最小的数 题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 思路 把两个int类型的数拼起来可能会比较大,溢出,我们可采用字符串来表示,处理大数问题 将数字转化为字符串,然后比较字符串的大小,此处的大小指的是:若str1+str2 > str2+str1,则str1 > str2, 我们需要重新定义一个compare函数 其实最后的连接起来的大小和

剑指offer 面试题33 把数组排成最小的数

题目链接: 剑指offer 题目链接: 把数组排成最小的数, 例如{3, 32, 321} 输出: 321323 解题思路: 我现在已经知道正确答案了, 就是没有办法去证明, 先去开会, 在开会的时候再去想. 代码: #include <iostream> #include <cstdio> #include <string> #include <vector> #include <cstring> #include <iterator&g

剑指offer (33) 把数组排成最小的数

题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接处的所有数字中最小的一个 例如输入数组 {3, 32, 321}则打印这3个数字能排成的最小数字 321323 两个数字m和n能拼接成数字mn和nm,如果mn < nm,则打印出mn,也就是m排在n之前,我们定义此时 m 小于 n,也就是相当于 自定义了qsort排序的 函数指针 本题拼接数字可能超出表达范围,需用大数解决 int compare(const void* strNumber1, const void* str

微软算法100题68 用数组排成最小的数

68.把数组排成最小的数.题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个.例如输入数组{32, 321},则输出这两个能排成的最小数字32132.请给出解决问题的算法,并证明该算法 1 package com.rui.microsoft; 2 3 import java.util.Arrays; 4 import java.util.Comparator; 5 6 public class Test68_Minimum { 7 8 public static

剑指Offer面试题33(java版):把数组排成最小的数

题目:输入一个正整数数组,把数组里面所有的数字拼接排成一个数,打印能拼接出的所有数字中的一个.例如输入数组{3,32,321},则打印出这3个数字能排成的最小数字321323. 这个题目最直接的做法应该是先求出这个数组中的所有数字的全排列,然后把每个排列拼接起来,最后求出排列起来的数字的最小值.求数组的排列和面试题28非常相似.根据排列组合的只是,n个数字总共有n!排列,我们再来看一下更快的算法. 这道题其实希望我们能够找到一个排序规则,数组根据这个规则排序之后能排成一个最小的数字.要确定排序的

剑指offer系列源码-把数组排成最小的数

题目1504:把数组排成最小的数 时间限制:1 秒内存限制:128 兆特殊判题:否提交:1463解决:448 题目描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为一个整数m (1<=m <=100)代表输入的正整数的个数. 输入的第二行包括m个正整数,其中每个正整数不超过10000000.