zoukankan      html  css  js  c++  java
  • 【编程题目】把数组排成最小的数

    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);
    
    }
  • 相关阅读:
    软件测试 -- 在配置测试中,如何判断发现的缺陷是普通问题还是特定的配置问题?
    软件测试 -- 测试中的“杀虫剂怪事”是指什么?
    软件测试 -- 配置和兼容性测试的区别
    软件测试 -- 和用户共同测试(UAT测试)的注意点有哪些
    软件测试 -- 测试人员和QA的区别
    软件测试 -- 所有的软件缺陷都能修复吗?所有的软件缺陷都要修复吗?
    软件测试 -- 发现的缺陷越多,说明软件缺陷越多吗?
    软件测试 -- 软件测试的风险主要体现在哪里
    软件测试 -- 什么是软件测试以及软件测试的目的是什么
    微信公众平台开发
  • 原文地址:https://www.cnblogs.com/dplearning/p/3920354.html
Copyright © 2011-2022 走看看