1. 引出及例题
《剑指Offer》面试题45:把数组排成最小的数:
输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
示例 1:
输入: [10,2]
输出: "102"
示例 2:
输入: [3,30,34,5,9]
输出: "3033459"
思路:
其解法是贪心的(贪心策略的证明详见书229页),就是将数组中的所有数字转换为字符串,再将各个字符串按照字典序从小到大进行排列,并进行拼接即为所求解的字符串,其中进行排序的过程会遇到大数问题,所以按照字典序进行比较排序是该题的重难点。
即自定义字符串比较器,若a+b>b+a
则a>b
,比如"3"+“23”>“23”+“3”,即"323">"233"则3>23,并且我们希望在排序的时候将23排在3的前面,也就是升序排列。
代码如下:
class Solution {
public:
string minNumber(vector<int>& nums) {
vector<string> strs;
string res;
for(auto& num : nums) {
strs.push_back(to_string(num));
}
//sort函数当中的compare即为自定义的字符串升序比较器
sort(strs.begin(), strs.end(), compare);
for(auto& str : strs) {
res += str;
}
return res;
}
private:
static bool compare(const string& str1, const string& str2) {
return str1 + str2 < str2 + str1;
}
};
2. sort的用法
- 其定义在algorithm头文件当中,使用要
#include <algorithm>
; - 第一个参数
RandomAccessIterator first
:数组名,也就是数组首地址,是一个随机迭代器类型的迭代器; - 第二个参数
RandomAccessIterator last
:数组名+n,其中n是你想从数组首地址开始,排序的数字元素的个数,也是随即迭代器类型的迭代器; - 第三个参数
Compare comp
:可以缺省,若是缺省的话按照默认的operator<
进行排序,即升序排序,若想自定义排序,须自定义返回值为布尔类型的排序函数。
注意:
- sort的前两个参数相当于是确定一个你想要排序的元素的地址所在的区间,从数学角度来讲,所以排序区间是一个左闭右开区间,所以第二个参数不是所要排序的最后一个元素的地址,而是进行排序的最后一个元素的后一个元素的地址;
- strict weak ordering严格弱排序:理解为升序即可;
- 好像是基于快排算法?官方文档给出的近似时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)。
举例:
// sort algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::sort
#include <vector> // std::vector
bool myfunction (int i,int j) {
return (i<j); }
struct myclass {
bool operator() (int i,int j) {
return (i<j);}
} myobject;
int main () {
int myints[] = {
32,71,12,45,26,80,53,33};
std::vector<int> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33
// using default comparison (operator <):
std::sort (myvector.begin(), myvector.begin()+4); //(12 32 45 71)26 80 53 33
// using function as comp
std::sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)
// using object as comp
std::sort (myvector.begin(), myvector.end(), myobject); //(12 26 32 33 45 53 71 80)
// print out content:
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
由上例子可以看出:
- 如果comp返回true,则第一个参数小于第二个参数,sort根据compare的返回值将第一个参数排在第二个参数之前,(即para1 < para2,则排列为para1, para2);
- 如果comp返回false,则第一个参数大于第二个参数,sort根据compare的返回值将第一个参数排在第二个参数之后, (即para1 > para2,则排列为para2, para1)。
★★★总结:
- sort函数根据comp函数的返回值,对comp函数的两个参数排序;
- 如果comp返回true,排序为“参数1”“参数2”,否则排序为“参数2”“参数1”;
- 想要升序排列,则
return parameter1<parameter2
,想要降序排列,则return parameter1>parameter2
。
3. Compare:C++的具名要求
对Compare的定义:
除了在算法中使用Compare函数,也可在容器类定义时指定compare,使得所添加元素满足自定义排序要求。
priority_queue<int, vector<int>, less<int>> maxHeap;
//less是实验性c++特性
//通过该语句可以得到最大堆
参考资料: