算法【贪心经典题目专题5】

题目一

测试链接:45. 跳跃游戏 II - 力扣(LeetCode)

分析:这道题用cur代表走完当前步数可以来到的最大长度,next代表如果多走一步可以来到的最大长度,然后遍历索引,如果当前步数可以来到的最大长度小于遍历到的索引,步数加1,最大长度更新为多走一步可以来到的最大长度,每一次遍历索引都会更新多走一步可以来到的最大长度。代码如下。

class Solution {
public:
    int jump(vector<int>& nums) {
        int length = nums.size();
        int cur = 0;
        int next = 0;
        int ans = 0;
        for(int i = 0;i < length;++i){
            if(cur < i){
                ++ans;
                cur = next;
            }
            next = max(i + nums[i], next);
        }
        return ans;
    }
};

题目二

测试链接:1326. 灌溉花园的最少水龙头数目 - 力扣(LeetCode)

分析:这道题思路和上道题差不多,用一个数组存储左边界从i开始的水龙头范围最右可以到达的下标。cur为当前水龙头数可以覆盖的最右下标,next是如果多用一个水龙头可以覆盖的最右下标。遍历下标,每次遍历更新多用一个水龙头可以覆盖的最右下标。如果当前水龙头数可以覆盖的最右下标等于遍历到的下标则需要判断,如果多用一个水龙头可以覆盖的最右下标依旧等于当前下标,则代表即使多用一个水龙头,也不能覆盖住后一个范围,所以返回-1;否则多用一个水龙头,当前最右下标更新为多用一个水龙头的最右下标。代码如下。

class Solution {
public:
    int right[10001] = {0};
    int minTaps(int n, vector<int>& ranges) {
        int start;
        for(int i = 0;i <= n;++i){
            start = max(0, i - ranges[i]);
            right[start] = max(i + ranges[i], right[start]);
        }
        int cur = 0;
        int next = 0;
        int ans = 0;
        for(int i = 0;i < n;++i){
            next = max(next, right[i]);
            if(cur == i){
                if(next == i){
                    return -1;
                }else{
                    ++ans;
                    cur = next;
                }
            }
        }
        return ans;
    }
};

题目三

测试链接:P1809 过河问题 - 洛谷

分析:这道题求最少渡河时间有两种方法,一种是让最少渡河时间依次和每一个人过到西岸,然后最少渡河时间划到东岸继续和另一个人渡河;另一种是让最小的两个渡河时间到西岸,然后最大的两个渡河时间一起到西岸,由西岸的最少渡河时间将船划到东岸。而具体是哪一种需要判断,所以需要使用动态规划。代码如下。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int N;
vector<int> person;
vector<int> dp;
int main(void){
    scanf("%d", &N);
    person.resize(N);
    for(int i = 0;i < N;++i){
        scanf("%d", &person[i]);
    }
    if(N == 1){
        printf("%d", person[0]);
    }else if(N == 2){
        printf("%d", max(person[0], person[1]));
    }else{
        dp.resize(N);
        sort(person.begin(), person.end());
        dp[0] = person[0];
        dp[1] = person[1];
        for(int i = 2;i < N;++i){
            dp[i] = min(dp[i-1] + person[0] + person[i],
                        dp[i-2] + person[0] + person[i] + person[1] + person[1]);
        }
        printf("%d", dp[N-1]);
    }
    return 0;
}

其中,dp数组表示0~i都到西岸且船留在西岸的最少渡河时间,可能性的展开就是两种,一是让西岸的最小渡河时间将船划到东岸和剩下的i一起到西岸;另一种是让最小渡河时间将船划到东岸,在东岸的i-1和i一起到西岸,船由现在西岸的最小渡河时间划到东岸,然后东岸的两个人一起到西岸。

题目四

测试链接:517. 超级洗衣机 - 力扣(LeetCode)

分析:这道题可以遍历每一个洗衣机,以遍历到的洗衣机为中转站,看中转站左边需要多少衣服,中转站右边需要多少衣服,求出最多需要多少操作步数使左右两边需要的衣服和已有的衣服相等。然后取最大操作步数即是答案。代码如下。

class Solution {
public:
    int findMinMoves(vector<int>& machines) {
        int length = machines.size();
        int sum = machines[0];
        for(int i = 1;i < length;++i){
            sum += machines[i]; 
        }
        if(sum % length != 0){
            return -1;
        }
        machines.push_back(0);
        int average = sum / length;
        int ans = 0;
        int left = 0, right = sum - machines[0];
        int left_deserve = 0, right_deserve = (length - 1) * average;
        int left_need = left_deserve - left, right_need = right_deserve - right;
        for(int i = 0;i < length;++i){
            if(left_need > 0 && right_need > 0){
                ans = max(ans, left_need + right_need);
            }else{
                ans = max(ans, max(abs(left_need), abs(right_need)));
            }
            left += machines[i];
            right -= machines[i+1];
            left_deserve += average;
            right_deserve -= average;
            left_need = left_deserve - left;
            right_need = right_deserve - right;
        }
        return ans;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还有糕手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值