贪心算法
是每次只考虑当前最优,目标证明每次是考虑当前最优能够达到局部最优,这就是贪心的思想,一般情况下贪心和排序一起出现,都是先根据条件进行排序,之后基于贪心策略得到最优结果。
面试的时候面试官一般不会出贪心算法,如果可能贪心一般都可以使用动态规划解决,面试官很喜欢出动态规划的题目。
1. 最大连续子序列
题目: 给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。
扩展1: 给定一个整数数组,找出两个 不重叠 子数组使得它们的和最大。
扩展2: 给定一个整数数组,找出两个不重叠的子数组A和B,使两个子数组和的差的绝对值|SUM(A) - SUM(B)|最大。
分析: 使用这个s表示当前可能满足的最大和,如果s>0,我们认为s对接下来的加操作有帮助,基于s+=nums[i],if s < 0, 认为s只会对后面造成负影响,两s=nums[i]。
扩展问题: 可以将 数组从每个位置k分开,分别结算[1,i]和[i+1, n)的最值,记录的过程中可以使用数组保存下来的已经计算好的值。
int maxSubArray(vector<int> &nums) {
int s = 0, ans = -1000000;
for(int i = 0; i < nums.size(); i ++) {
if(s > 0) s += nums[i];
else s = nums[i];
ans = max(s, ans);
}
return ans;
}
2. 删除数字
题目: 给定一个以字符串表示的非负整数,从该数字中移除掉k个数位,让剩余数位组成的数字尽可能小,求可能的最小结果。
分析: 从左到右遍历字符串,找到第一个不满足递增的数字删除,一定会保证当前操作之后剩下的数字最小。
string removeKdigits(string &num, int k) {
int i;
while(k --) {
for(i = 0; i < num.size() - 1 && num[i] <= num[i+1]; i ++);
num.erase(num.begin() + i);
}
// remove 0
auto it = num.begin();
while(it != num.end() && *it == '0') {
num.erase(it);
it = num.begin();
}
if(num.size() == 0) num = "0";
return num;
}
3. 无重叠区间
题目: 给定一些区间,找到需要移除的最小区间数&#x