贪心算法OJ刷题(1)

这篇具有很好参考价值的文章主要介绍了贪心算法OJ刷题(1)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

贪心算法

指所求问题的整体最优解可以通过一系列局部最优的选择来到达。是不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。每一步只考虑一个数据,它的选取应该满足局部优化的条件。若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加算法停止。

该算法不能求解最值问题。

选择排序

它所采用的贪心策略即为每次从未排序的数据中选取最小值并把最小值放在未排序数据的起始位置,直到未排序的数据为0,则结束排序。

在数据结构中我写的选择排序是经过优化的,一次找两个数(最大值和最小值)。但是思路是一样的。

void swap(int* array, int i, int j)
{
    int tmp = array[i];
    array[i] = array[j];
    array[j] = tmp;
}
void selectSort(int* arr, int n){
    int minIndex = 0;
    // i: 未排序数据的起始位置
    for(int i = 0; i < n; i++)
    {
        // 从所有未排序的数据中找最小值的索引
        for(int j = i + 1; j < n; j++)
        {
            if(arr[j] < arr[minIndex]) minIndex = j;
        }
        swap(arr, i, minIndex);
    }
}

分割平衡字符串

题目描述

平衡字符串 中,‘L’ 和 ‘R’ 字符的数量是相同的。给你一个平衡字符串 s,请你将它分割成尽可能多的子字符串,并满足:每个子字符串都是平衡字符串。

返回可以通过分割得到的平衡字符串的 最大数量 。

解题思路

题目要求通过分割得到平衡字符串的最大数量,即尽可能多的分割。

贪心策略: 不要有嵌套的平衡串,只要目前字符串达到平衡,就立即分割。故可以定义一个变量balance,在遇到不同的字符时,向不同的方向变化,当balance为0时达到平衡,分割数更新。

比如:从左往右扫描字符串s,遇到R, balance - 1;遇到L,balance + 1;当balance为0时即,更新记录cnt ++;如果最后cnt==0,说明s只需要保持原样,返回1

class Solution {
public:
    int balancedStringSplit(string s) {
        //贪心策略:遇到平衡的就++,不嵌套
        int count = 0;
        int balance = 0;
        for(auto &e: s)
        {
            if(e == 'L') ++balance;
            else --balance;

            if(balance == 0) ++count;
        }
        return count;
    }
};

买卖股票的最佳时机 II

题目描述

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

解题思路

连续上涨交易日: 则第一天买最后一天卖收益最大,等价于每天都买卖

连续下降交易日: 则不买卖收益最大,即不会亏钱。

故可以遍历整个股票交易日价格列表,在所有上涨交易日都买卖(赚到所有利润),所有下降交易日都不买卖(永不亏钱)。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        //贪心策略:如果第2天比第1天的高,就在第1天买入第二天卖出。低的话就不操作
        int money = 0;
        for(int i = 1; i < prices.size(); ++i)
        {
            if(prices[i-1] < prices[i])
            {
                money += (prices[i] - prices[i-1]);
            }
        }
        return money;
    }
};

跳跃游戏

题目描述

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

解题思路

设想一下,对于数组中的任意一个位置 y,我们如何判断它是否可以到达?根据题目的描述,只要存在一个位置 i,它本身可以到达,并且它跳跃的最大长度为 i + nums[i],这个值大于等于 y,即 i+nums[i] ≥ y,那么位置y也可以到达。换句话说,对于每一个可以到达的位置 x,它使得 i+1, i+2,⋯, i+nums[i] 这些连续的位置都可以到达。

依照上述思路,我们依次遍历数组中的每一个位置,并实时更新最远可以到达的位置。对于当前遍历到的位置i,如果它在 最远可以到达的位置的范围内,那么我们就可以从起点通过若干次跳跃到达该位置,因此我们可以用 下标i+nums[i]更新 最远可以到达的位置。

在遍历的过程中,如果最远可以到达的位置大于等于数组中的最后一个位置,那就说明最后一个位置可达,我们就可以直接返回True作为答案。反之,如果在遍历结束后,最后一个位置仍然不可达,我们就返回 False 作为答案。

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int maxNum = 0;//目前能到的最远的地方
        int n = nums.size();
        bool can = false;//是否走到目的地
        for(int i = 0; i < n; ++i)
        {
            //每走一步就更新最远能到的下标
            if(maxNum >= i)
            {
                maxNum = max(maxNum, i + nums[i]);
            }
            // 如果最大能够到达的位置已经到达数组末尾,说明必然可以到达
            if(maxNum >= n-1) 
            {
                can = true;
                break;
            }
            // 如果当前最远可以到达的位置未超过当前位置,肯定无法到达数组末尾
            if(maxNum < i) 
            {
                break;
            }
        }
        return can;
    }
};

纸币找零

题目描述

假设1元、2元、5元、10元、20元、50元、100元的纸币分别有c0, c1, c2, c3, c4, c5, c6张。现在要用这些钱来支付K元,最少可以用多少张纸币完成支付?

vector<vector> = { {面值, 张数}, {面值, 张数}, … };

解题思路

用贪心算法的思想,很显然,每一步尽可能用面值大的纸币即可。文章来源地址https://www.toymoban.com/news/detail-425119.html

#include<iostream>
#include<algorithm>
using namespace std;
int solve(int money,const vector<pair<int,int>>& moneyCount)
{
    int num = 0;
    //首先选择最大面值的纸币
    for (int i = moneyCount.size() - 1; i >= 0; i--)
    {
        //需要的当前面值数量 与 原面值数量 取最小
        //比如张数为0时,就不可以取该面值的纸币
        int c = min(money / moneyCount[i].first, moneyCount[i].second);
        money = money - c * moneyCount[i].first;
        num += c;
    }
    if (money > 0)//说明现有纸币无法完成交易
    	num = -1;
	return num;
}
int main()
{
    //存放纸币与数量: first:纸币,second:数量
    vector<pair<int, int>> moneyCount = { { 1, 3 }, { 2, 1 }, { 5, 4 }, { 10, 3 }, { 20, 0 }, {50, 1}, { 100, 10 } };
    int money;
    cout << "请输入要支付的钱" << endl;
    cin >> money;
    int res = solve(money, moneyCount);
    if (res != -1)
    	cout << res << endl;
    else
    	cout << "NO" << endl;
    return 0;
}

到了这里,关于贪心算法OJ刷题(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【刷题篇】贪心算法(一)

    【刷题篇】贪心算法(一)

    假设1元、2元、5元、10元、20元、50元、100元的纸币分别由c0,c1,c2,c3,c4,c5,c6张。现在要用这些钱来支付K元,至少要用多少张纸币?

    2024年02月09日
    浏览(13)
  • 【刷题篇】贪心算法

    【刷题篇】贪心算法

    假设1元、2元、5元、10元、20元、50元、100元的纸币分别由c0,c1,c2,c3,c4,c5,c6张。现在要用这些钱来支付K元,至少要用多少张纸币?

    2024年02月09日
    浏览(14)
  • 【算法日志】贪心算法刷题:重叠区问题(day31)

    【算法日志】贪心算法刷题:重叠区问题(day31)

    目录 前言 无重叠区间(筛选区间) 划分字母区间(切割区间)  合并区间 今日的重点是掌握重叠区问题。

    2024年02月12日
    浏览(12)
  • 【算法刷题 | 贪心算法04】4.26(跳跃游戏、跳跃游戏||)

    【算法刷题 | 贪心算法04】4.26(跳跃游戏、跳跃游戏||)

    给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 示例一: 示例二: 6.2.1贪心思路 一般思路:当前位置元素如果是 3,我究竟

    2024年04月27日
    浏览(9)
  • OJ刷题---[算法课动态规划]走网格(C++完整代码)

    OJ刷题---[算法课动态规划]走网格(C++完整代码)

    m行n列的网格,从左上角(1,1)出发,每一步只能向下或者向右,问共有多少种方法可以走到右下角(m,n); 输入参数 m n (1=m=10 1=n=10) 输出多少种走法 比如: 输入:2 3 输出:3 输入:5 5 输出:70 完整代码(C++): 结果: 注意:最后调用的时候,是调用sum(m,n),而不是sum(m+1

    2024年02月07日
    浏览(14)
  • LeetCode刷题笔记【23】:贪心算法专题-1(分发饼干、摆动序列、最大子序和)

    LeetCode刷题笔记【23】:贪心算法专题-1(分发饼干、摆动序列、最大子序和)

    贪心的本质是选择每一阶段的局部最优,从而达到全局最优。 例如,有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿? 指定每次拿最大的,最终结果就是拿走最大数额的钱。 每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优。 感觉像

    2024年02月09日
    浏览(16)
  • 分享刷题的一些小知识点--4.9日

    1.string库提供了 、、==、=、=、!= 等比较运算符,比如两个字符串s和t,直接(s==t)是正确的。 2.unordered_map 容器,直译过来就是\\\"无序 map 容器\\\"的意思。所谓“无序”,指的是 unordered_map 容器不会像 map 容器那样对存储的数据进行排序。换句话说,unordered_map 容器和 map 容器仅有

    2023年04月11日
    浏览(13)
  • 我写了一个用来刷题的微信小程序

    我写了一个用来刷题的微信小程序

    目录 土著刷题是一个什么工具? 为什么要做土著刷题这样一个产品? 当前版本的规划 版本效果 土著刷题微信小程序,一款免费的刷题小程序,提供多种刷题模式,可以分享题库给小伙伴一起刷,针对特定题库的用户群体。 对于为什么要开发这个刷题小程序,这可以说是一

    2024年02月10日
    浏览(11)
  • C/C++ leetcode刷题的各种小tips记录

    优先级 运算符 结合性 1 ()(括号/函数运算符)        [](下标运算符)  .(成员选择(对象))        -(成员选择(指针)) 从左到右 2 !(逻辑非)        ~(按位取反) +(正)        -(负) ++        -- *(取值运算符)        (取地址运算符) (type)(强制类型转换) 从右到左 3 *(乘)       

    2024年02月08日
    浏览(13)
  • 力扣算法刷题Day34|贪心:K次取反后最大化的数组和 加油站 分发糖果

    力扣题目:# 1005.K次取反后最大化的数组和  刷题时长:10min 解题方法:贪心 复杂度分析 时间O(n) 空间O(1) 问题总结 无 本题收获 贪心思路:两次贪心 在包含正负无序的整数数组中,如何转变K次正负,让数组和达到最大 局部最优:让绝对值大的负数变为正数,当前数值达到

    2024年02月09日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包