1.拼接所有的字符串产生字典序最小的字符串
给定一个字符串的数组strs,请找到一种拼接顺序,使得所有的字符串拼接起来组成的字符串是所有可能性中字典序最小的,并返回这个字符串。
首先引入比较器:(摘自如何自定义sort函数中的比较函数)
1)比较器的定义:(当然可以更复杂的实现)函数比较器
bool myfunction (int i,int j) { return (i<j); }
或者:函数对象比较器
struct myclass {
bool operator() (int i,int j) { return (i<j);}
} myobject;
2)比较器的使用:
// using function as comp
sort (myvector.begin()+4, myvector.end(), myfunction);
// using object as comp
sort (myvector.begin(), myvector.end(), myobject);
comp函数返回一个bool类型的值,这个值表示了在严格弱排序中(可以理解为升序排序)第一参数是否位于第二个参数之前。
也就是说如果comp返回true,则第一个参数小于第二个参数,sort根据compare的返回值将第一个参数排在第二个参数之前。
如果comp返回false,则第一个参数大于第二个参数,sort根据compare的返回值将第一个参数排在第二个参数之后。
传入A,B,定义bool myfunction (int i,int j) { return (i<j); }
,作为comp函数,则排列AB。
传入BA,则排列AB。
可以看出是升序排列的。(sort函数默认的comp函数也是默认升序的)
而如果我们定义bool myfunction (int i,int j) { return (i>j); }
,作为comp函数,
传入AB,返回false,则排列为BA,
传入BA,返回true,排列为BA。
是降序排列的。
总结起来就是:
sort函数根据comp函数的返回值,对comp函数的两个参数排序。
如果comp返回true,排序为“参数1”“参数2”,否则排序为“参数2”“参数1”。
想要升序排列,则return parameter1<parameter2
想要降序排列,则return parameter1>parameter2
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
//自定义比较器
bool cmp(string str1,string str2){
return str1+str2<str2+str1;
}
int main(){
int n;
cin>>n;
string s[n],s1;
for(int i=0;i<n;i++){
cin>>s[i];
}
//比较从开始到结束,若为vector则s.begin(),s.end()
sort(s,s+n,cmp);
for(auto c:s){
cout<<c;
}
}
2.把数组排成最小的数(类似题目)
class Solution {
public:
//注意加static
static bool cmp(string n1,string n2){
return n1+n2<n2+n1;
}
string minNumber(vector<int>& nums) {
vector<string> s;
string str;
for(int i=0;i<nums.size();i++){
//to_string数字转字符串
s.push_back(to_string(nums[i]));
}
sort(s.begin(),s.end(),cmp);
for(auto c:s){
str+=c;
}
return str;
}
};
2.切黄金
给定一个正数数组arr,arr的累加和代表金条的总长度,arr的每个数代表金条要分成的长度。规定长度为K的金条只需分成两块,费用为K个铜板。返回把金条分出arr中的每个数字的最小代价。
其本质是个哈夫曼编码,用小根堆,每次找出两个最小的合并且加入堆,并将两个元素从堆中删除,最后堆中只剩一个元素,那么就是最开始的长度,这里需要注意的是,其实就是把题目描述逆向了,每一次的花费都得累加。
#include<iostream>
#include<queue>
#include <vector>
#include <windows.h>
using namespace std;
int main(){
int n,res=0;
cin>>n;
int num[n];
//小根堆
priority_queue<int,vector<int>,greater<int>> p;
for (int i=0;i<n;i++){
cin>>num[i];
p.push(num[i]);
}
while(p.size()>1){
int a=p.top();
p.pop();
int b=p.top();
p.pop();
//每次切都得花费
res+=a+b;
p.push(a+b);
}
cout<<res<<endl;
system("pause");
}
3.IPO
两个堆,一个小根堆按照花费资金排序,一个大根堆按照收益排序。这样根据现有的资金数,可以去小根堆内找到资金能做的项目,再加入大根堆,此时,在大根堆的top()元素就是自己的最大收益。
class Solution {
public:
int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
//大根堆放置利润
priority_queue<int,vector<int>,less<int>> pro;
//小根堆放置成本
priority_queue<pair<int ,int> , vector<pair<int,int>>, greater<pair<int,int>>> cap;
for(int i=0;i<Profits.size();i++){
cap.push(make_pair(Capital[i], Profits[i]));
}
//一共做K个项目
for (int i = 0; i < k; i++){
//把当前能做的项目获得的利润放入大根堆
while(W>=cap.top().first && !cap.empty()){
pro.push(cap.top().second);
cap.pop();
}
//如果没有能做的项目就返回当前W
if(pro.empty())return W;;
W+=pro.top();
//该项目做完了,不能再做,pop()
pro.pop();
}
return W;
}
};