32.把数组排成最小的数

题目

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

思路一

  • 对数组中的数字进行全排列,依次拼接起来比较得到最小的值。
  • 全排列的时间复杂度为O(n!)。

代码

class Solution {
private:
    string resMinStr = "";
public:
    string PrintMinNumber(vector<int> numbers) {
        if ( !numbers.size() ) return "";
         
        helper( numbers, 0 );
         
        return resMinStr;
    }
     
    void helper( vector<int>& numbers, int start ) {
        if ( numbers.size() == start ) {
            if ( numbers[0] == 0 ) return;
             
            string tempStr = "";
            constuctStr( numbers, tempStr );
             
            if ( resMinStr.empty() || lessThanMinStr(tempStr) )
                resMinStr = tempStr;
             
            return;
        }
         
        for ( int i = start; i < numbers.size(); ++i ) {
            swap( numbers[i], numbers[start] );
            helper( numbers, start+1 );
            swap( numbers[i], numbers[start] );
        }
         
        return;
    }
     
    void swap( int& a, int& b ) {
        int temp = a;
        a = b;
        b = temp;
         
        return;
    }
     
    void constuctStr( vector<int>& nums, string& str ) {
        for ( auto& n : nums )
            str += to_string( n );
    }
     
    bool lessThanMinStr( string& str ) {
        bool flag = false;
        for ( int i = 0; i < str.size(); ++i ) {
            if ( resMinStr[i] > str[i] ) {
                flag = true;
                break;
            }
             
            if ( resMinStr[i] < str[i] )
                break;
        }
         
        return flag;
    }
};

思路二

  • 定义一种排序规则。如果有数字a、b,拼接的结果有ab和ba,如果ab>ba,则我们称a>b。
  • 使用这种规则对数组进行排序,然后将数组中的元素拼接为字符串。
  • 复杂度在于排序算法的复杂度。
  • 我使用冒泡和快排两种。

冒泡

class Solution {
public:
    string PrintMinNumber(vector<int> numbers) {
        mySort( numbers );
        
        string resStr = "";
        constructStr( numbers, resStr );
        
        return resStr;
    }
    
    void mySort( vector<int>& nums ) {
        for ( int i = 0; i < nums.size(); ++i ) {
            for ( int j = i+1; j < nums.size(); ++j ) {
                if ( moreThan(nums[i], nums[j]) )
                    swap( nums[i], nums[j] );
            }
        }
        
        return;
    }
    
    bool moreThan( int a, int b ) {
    	// 判断a是否大于b
        bool flag = false;
        string APlusB = to_string(a) + to_string(b);
        string BPlusA = to_string(b) + to_string(a);
        
        int i = 0;
        while ( i < APlusB.size() ) {
            if ( APlusB[i] > BPlusA[i] ) {
                flag = true;
                break;
            }
            
            if ( APlusB[i] < BPlusA[i] )
                break;
            
            ++i;
        }
        
        return flag;
    }
    
    void swap( int& a, int& b ) {
        int temp = a;
        a = b;
        b = temp;
        
        return;
    }
    
    void constructStr( vector<int>& nums, string& resStr ) {
        for ( auto& n : nums )
            resStr += to_string(n);
        
        return;
    }
};

快排

只需把冒泡部分换为快排,替换的代码为

void mySort(vector<int> &nums, int lo, int hi) {
    if (hi - lo < 1)
        return;
    int mid = partition(nums, lo, hi);

    mySort(nums, lo, mid - 1);
    mySort(nums, mid + 1, hi);

    return;
}

int partition(vector<int> &nums, int lo, int hi) {
    int index = lo + rand() % (hi - lo + 1);
    swap(nums[lo], nums[index]);
    int pivot = nums[lo];

    while (lo < hi) {
        while (lo < hi && lessEqualThan(pivot, nums[hi]))
            --hi;

        nums[lo] = nums[hi];

        while (lo < hi && moreEqualThan(pivot, nums[lo]))
            ++lo;

        nums[hi] = nums[lo];
    }

    nums[lo] = pivot;

    return lo;
}

bool lessEqualThan(int &a, int &b) {
    bool flag = true;

    string APlusB = to_string(a) + to_string(b);
    string BPlusA = to_string(b) + to_string(a);

    int i = 0;
    while (i < APlusB.size()) {
        if (APlusB[i] > BPlusA[i]) {
            flag = false;
            break;
        }

        if (APlusB[i] < BPlusA[i])
            break;

        ++i;
    }

    return flag;
}

bool moreEqualThan(int &a, int &b) {
    bool flag = true;

    string APlusB = to_string(a) + to_string(b);
    string BPlusA = to_string(b) + to_string(a);

    int i = 0;
    while (i < APlusB.size()) {
        if (APlusB[i] < BPlusA[i]) {
            flag = false;
            break;
        }

        if (APlusB[i] > BPlusA[i])
            break;

        ++i;
    }

    return flag;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值