贪心, 每一步最优来实现最终结果最优。如果不用贪心, 一步一步枚举则会导致时间复杂度过高,导致超过了算法题的时间限制。但是贪心往往是比较难证明的,在面试或者竞赛中,就需要我们学会去猜想,大胆去实践,而不是把时间花在证明上。
如何去猜想,就需要在处理一小部分数据时,根据题目的意思使局部最优化,方法包括条件范化宽松化,条件分步走等,这需要我们在做题中不断积累。我们今天来以力扣179题来说明贪心如何去运用:
题目:
给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。
注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。示例:
输入:nums = [10,2]
输出:“210”
- 分析:这相当于一个给数字排列的问题,问题的关键的一小步是怎么确定两个数字之间的顺序, 如果确定了,那么下面就好做了。根据题目中合成最大数原则,可以泛化到两个数上,两个数就两种不同排列,很好比较大小, 那么整个数组就很好排序了。具体实现见代码:
- 技巧:本例中还有几个实用小技巧,比如:大数连接可以通过字符串相加,比较大小可以直接通过字符串比较,这样效率比较高。
class Solution {
public:
static int cmp(int a, int b){
char ac[21], bc[21], temp[21];
sprintf(ac, "%d", a);
sprintf(bc, "%d", b);
strcpy(temp, ac);
strcat(ac, bc);
strcat(bc, temp);
//cout<<ac<<" ac"<<endl;
//cout<<bc<<" bc"<<endl;
return (strcmp(ac,bc)<0)?0:1;
}
string largestNumber(vector<int>& nums){
string s("0");
if(nums.size() == 0){
return s;
}
int i = 0;
for(i = 0; i < nums.size();i++){
if(nums[i]!= 0){
break;
}
}
if(i == nums.size()){
return s;
}
sort(nums.begin(),nums.end(), cmp);
string res("");
for (int i = 0; i < nums.size();i++){
//cout<<nums[i]<<" = nums["<<i<<"]"<<endl;
res += to_string(nums[i]);
}
return res;
}
};