贪心算法
贪心算法
- 贪心算法Greedy
- 贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的解法。
- 贪心算法与动态规划的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。
- 贪心法可以解决一些最优化问题,如:求图中的最小生成树,求哈夫曼编码等。然而对于工程和生活中的问题,贪心法一般不能得到我们要求的答案。
- 一旦一个问题可以通过贪心法来解决,那么贪心法一般是解决这个问题的最好办法,由于贪心法的高效性以及其求得的答案比较接近最优结果,贪心法也可以用作辅助算法或者直接解决一些要求结果不特别精确的问题。
实战题目
零钱兑换
当硬币可选集合固定:Coins = [20, 10, 5, 1]
求最少可以几个硬币拼出总数。 比如 total = 36
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
//Coin required store for amount from 0 to amount.
int coin_required[amount+1] = {0};
//Calculate for coin required for amount 1 till amount.
for(int i = 1; i <= amount; i++ )
{
//To start with set the min coin value to high .
int min_coin_required = 1e8;
for(int c = 0; c < coins.size(); c++ )
{
int coin_value = i - coins[c];
//Coin value becomes -ve after giving the coin.
//Don't use the coin, cotinue
if(coin_value < 0)
continue;
else if(coin_value == 0)
{
//Got perfect coin match for the amount.
min_coin_required = 1;
break;
}
else
{
//Post using the coin_value check for remaining
//amount, if remaining amount can't be given, no point in
//proceeding with this coin value.
if(coin_required[coin_value] != 1e8)
{
//Existing solution is available add current coin in the existing solution.
min_coin_required = min(min_coin_required, coin_required[coin_value] + 1);
}
}
}
//Set the value for amount i.
coin_required[i] = min_coin_required;
}
//Coins are not available for this amount.
if(coin_required[amount] == 1e8)
return -1;
return coin_required[amount];
}
};
适用贪心算法的场景
- 简单地说,问题能够分解成子问题来解决,子问题的最优解能递推到最终问题的最优解。这种子问题最优解成为最优子结构。
- 贪心算法与动态规划的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会抱保护以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。
LeetCode实战练习
class Solution {
public:
bool lemonadeChange(const vector<int>& bills) {
int five = 0, ten = 0;
for (const auto& bill : bills)
if (bill == 5) five++;
else if (bill == 10 && 0 < five) --five, ++ten;
else if (0 < ten && 0 < five) --five, --ten;
else if (2 < five) five-=3;
else return false;
return true;
}
};
class Solution {
public:
int maxProfit(vector<int>& prices) {
//快慢指针标记
int i=0,j=1,sum=0;
//判断vector大小
if(prices.size()<=1)
return 0;
//两个指针一直紧挨在一起,只有j的值大于i的值时,就把差值加入sum中
while(j<prices.size()){
if(prices[j]-prices[i]>0)
sum+=(prices[j]-prices[i]);
i++;
j++;
}
return sum;
}
};
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(), g.end());
sort(s.begin(), s.end());
int j = 0;
int i = 0;
while(i < g.size() && j < s.size()){
if(g[i] <= s[j]){
i++;j++;
} else {
j++;
}
}
return i;
}
};
class Solution {
public:
void left(char& c)
{
if(c == 'U') c = 'L';
else if(c == 'L') c = 'D';
else if(c == 'D') c = 'R';
else c = 'U';
}
void right(char& c)
{
if(c == 'U') c = 'R';
else if(c == 'R') c = 'D';
else if(c == 'D') c = 'L';
else c = 'U';
}
int distance(pair<int,int> curr_point)
{
return curr_point.first * curr_point.first + curr_point.second * curr_point.second;
}
struct pair_hash
{
template <class T1, class T2>
std::size_t operator () (std::pair<T1, T2> const &pair) const
{
std::size_t h2 = std::hash<T2>()(pair.second);
return h1 ^ h2;
}
};
int robotSim(vector<int>& commands, vector<vector<int>>& obstacles) {
char c = 'U';
pair <int,int> curr_point = make_pair(0,0);
unordered_set < pair<int,int> , pair_hash> obs;
int dist = 0;
for(auto w: obstacles) obs.insert(make_pair(w[0],w[1]));
for(int i = 0; i < commands.size(); ++i)
{
if(commands[i] == -1) right(c);
else if(commands[i] == -2) left(c);
else
{
bool obstacle = false;
for(int j = 1; j <= commands[i] and not obstacle; ++j)
{
if(c == 'R')
{
if(obs.find(make_pair(curr_point.first+1,curr_point.second)) != obs.end())
{
obstacle = true;
}
else curr_point.first += 1;
}
else if(c == 'U')
{
if(obs.find(make_pair(curr_point.first,curr_point.second+1)) != obs.end())
{
obstacle = true;
}
else
{
curr_point.second += 1;
}
}
else if(c == 'D')
{
if(obs.find(make_pair(curr_point.first,curr_point.second-1)) != obs.end())
{
obstacle = true;
}
else curr_point.second -= 1;
}
else if(c == 'L')
{
if(obs.find(make_pair(curr_point.first-1,curr_point.second)) != obs.end())
{
obstacle = true;
}
else curr_point.first -= 1;
}
dist = max(dist,distance(curr_point));
}
}
}
return dist;
}
};
class Solution {
public:
bool canJump(vector<int>& nums) {
int i,minjump=0;
for(i=nums.size()-2;i>=0;i--){
minjump++;
if(nums[i]>=minjump)minjump=0;
}
if(minjump==0)return true;
else return false;
}
};