LeetCode刷题——贪心法(C/C++)

这里写目录标题

  • [中等]买卖股票的最佳时机 II
  • [中等]移掉k位数字
  • [中等]跳跃游戏
  • [中等]跳跃游戏 II
  • [中等]加油站
  • [中等]划分字母区间
  • [中等]无重叠区间
  • [中等]用最少数量的箭引爆气球

[中等]买卖股票的最佳时机 II

  • 原题链接
  • 题解
    最简单的思路,效率不高,只要明天的股价大于今天的,就把这个差值算上,(因为允许你当天卖当天买)只要有正的差额,都不放过。(现实中炒股也这么美好就好了)
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int maxn = 0;
        for(int i=0;i<prices.size()-1;i++){
            if(prices[i]<prices[i+1]) maxn += prices[i+1]-prices[i]; 
        }
        return maxn;
    }
};

[中等]移掉k位数字

  • 原题链接
  • 题解
    主要思路就是在入栈的时候,如果当前元素比栈顶元素小,并且还没有删到k个数,就将栈顶元素出栈,这题的判断条件很繁杂,前导0我就判断了两次,先是在字符入栈的时候就判断一次,最后转化成字符串输出时又要再算一次

在思路正确的情况下,最后一个用例一直过不去,超时,然后就想到问问chatgpt,最后他帮我优化了代码的效率,主要卡在两个问题上:

①substr()的效率很低,循环使用时间复杂度很高,我原先是循环使用substr在输出前删除前导0,比较傻的做法。

while(answer.size()>0 && answer[0] == '0'){
    answer = answer.substr(1,answer.size()-1);
}

②原先出栈转字符串的操作也是类似用字符串循环拼接的思路,说明字符串拼接或者剪切本身复杂度是比较高的,最好是不要循环使用

 //出栈转化结果
        string answer = "";
        while (ans.size() > 0) {
            answer = ans.top() + answer;
            ans.pop();
        }

最后是修改后正确通过的代码

class Solution {
public:
    string removeKdigits(string num, int k) {
        if (num.size() == k) return "0";
        int m = k;
        stack<char> ans;
        int i;
        for (i = 0; i < num.size() && m != 0; i++) {
            while (m > 0 && ans.size() > 0 && ans.top() > num[i]){
			    ans.pop();
			    m--;
            }
            if (num[i] != '0' || ans.size() > 0) {
                ans.push(num[i]);
            }
        }
        while(i<num.size()) ans.push(num[i++]);
        while((m--)>0 && ans.size()>0) ans.pop();
        //出栈转化结果
        string answer(ans.size(), ' ');
        int j = ans.size() - 1;
        while (!ans.empty()) {
            answer[j--] = ans.top();
            ans.pop();
        }
        //再次删除前导0
        int index = 0;
        while (index < answer.size() && answer[index] == '0') {
            index++;
        }
        if(answer.size() == 0) return "0";
        return answer.substr(index == answer.size() ? index - 1 : index, answer.size());
    }
};

ps:ChatGPT关于优化这个算法给出的建议
在这里插入图片描述

[中等]跳跃游戏

  • 原题链接
  • 题解
int flag[30100];
class Solution {
public:
    bool canJump(vector<int>& nums) {
        if(nums.size() == 1) return true;
        if(nums.size() == 0) return false;
        for(int i=1;i<nums.size();i++){
            flag[i] = 0;
        }
        flag[0] = 1;
        for(int i=0;i<nums.size()-1;i++){
            if(flag[i] == 1){
                for(int j=1;j<=nums[i];j++){
                    if(i+j == nums.size()-1) return true;
                    flag[i+j] = 1;
                }
            }   
        }
        return false;
    }
};

[中等]跳跃游戏 II

  • 原题链接
  • 题解
    基本跟上一题差不多,记得初始化的时候,flag[]里面,除了第一个元素是0,他本身可以0步到达自己,其他都是int的最大值,用于后面的min函数比较,每一次循环就将当前位置能达到的所有下标的值进行一个比较,如果当前位置值+1,比原先记录到达当前下标需要的最小步数小,则更新。
int flag [10001];
class Solution {
public:
    int jump(vector<int>& nums) {
        if(nums.size() == 0) return 0;
        for(int i=1;i<nums.size();i++){
            flag[i] = INT_MAX;
        }
        flag[0] = 0;
        for(int i=0;i<nums.size()-1;i++){
            for(int j=1;j<=nums[i] && i+j<nums.size();j++){
                flag[i+j] = min(flag[i] + 1,flag[i+j]);
            }   
        }
        return flag[nums.size()-1];
    }
};

[中等]加油站

  • 原题链接
  • 题解
    当j走到一个位置无法前进的时候,说明i~j中间都是无法作为起点的,对i~j中间任意一点k,若以k作为起点,那么出发时的汽油储量只有gas[k],而从k之前的点i走过来,汽油储量应该>=gas[k](能够顺利走到k点,到的时候汽油起码是0),所以下一层循环可以直接从j+1开始考虑作为起点。
class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int gasCount;
        int n = gas.size();
        for(int i=0; i<n; i++){
            int j = i;
            gasCount = gas[i];
            while (gasCount - cost[j] >= 0) {
                if (gasCount + gas[(j+1)%n] - cost[j] >= 0) {
                    gasCount = gasCount + gas[(j+1)%n] - cost[j];
                    j = (j + 1) % n;
                    if(j==i) return i;
                }
            }
            if(j < i) return -1;
            i = j;
        }
        return -1;
    }
};

以下代码就是暴力的思路,每次查找失败都是i++,导致时间复杂度过大,最后超时,有五个样例通不过,但是思路上是比较朴素能够想到的,上面那个正确的就可以基于这个思路得到。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int i = 0;
        int j = 0;
        int gasCount = 0;
        int n = gas.size();
        while (i < n) {
            gasCount += gas[j];
            if (gasCount - cost[j % n] >= 0) {
                gasCount -= cost[j % n];
                j = (j + 1) % n;
                if(j==i) return i;
            }
            else {
                //重置起点
                i++;
                j = i;
                gasCount = 0;
            }
        }
        return -1;
    }
};

[中等]划分字母区间

  • 原题链接
  • 题解
    先开个int数组或者map记录一下字符串里面各个字母出现的次数,在循环的过程中,检查当前扫描到的字母出现的次数,如果和最大次数相同,说明当前段已经包含了这个字母的所有取值,kinds用于记录当前段中,出现次数已经达到最大的字母的数量,如果和map的大小相等,说明当前段所有字母都取到了最大数,则返回当前段长,并清空记录信息,继续向前循环。
class Solution {
public:
    vector<int> partitionLabels(string s) {
        int count[26];
        map<char,int> nowKinds;
        int kinds = 0;
        int length = 0;
        vector<int> ans;
        int n = s.size();
        for(int i=0;i<26;i++){
            count[i] = 0;
        }
        //记录各字母出现频次
        for(int i=0;i<n;i++) count[s[i]-'a']++;
        for(int i=0;i<n;i++){
            nowKinds[s[i]]++;
            if(nowKinds[s[i]] == count[s[i]-'a']) kinds++;
            length++;
            if(nowKinds.size() == kinds){
                ans.push_back(length);
                length = 0;
                nowKinds.clear();
                kinds = 0;
            }
        }
        return ans;
    }
};

[中等]无重叠区间

  • 原题链接
  • 题解
    贪心的思路在于,对所有重叠的区间来说,只能取其中一个,其他都要放弃,在按右端点排序所有区间的条件下,尽可能选择右端点数字最小的,能够尽可能把右边空间空出去选择更多区间。
    ①将区间按右端点排序,然后从小到大循环,如果当前区间左端点大于等于上一次选择区间的右端点,则可以加入,并将pre更新为当前区间右端点,否则取出。
    ②有个坑就是样例通过之后还是显示超时,compare函数应该使用引用传参,这样会提高效率,原因chatpgt说的是能够减少复制开销
    在这里插入图片描述
class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if(intervals.empty()) return 0;
        int n = intervals.size();
        sort(intervals.begin(),intervals.end(),compare);
        //记录上一个区间的右边界,最初始的为第一组数
        int pre = 0;
        int length = 0;
        for(int i=1; i<n; i++){
            if(intervals[i][0] >= intervals[pre][1]){
                pre = i;
            }else{
                length++;
            }
        }
        return length;
    }
    static bool compare(vector<int> &a, vector<int> &b){
        return a[1] < b[1];
    }
};

[中等]用最少数量的箭引爆气球

  • 原题链接
  • 题解
    其实就是判断重叠区间的问题,相比起上面那题无重叠区间,这里要判断的是如果区间有重叠区间就可以少射一支箭,箭数 = 区间总数-重叠次数,记住一个问题就是如果区间头尾相接,也算是能够一支箭射中两个。
class Solution {
public:
    //重叠区间的问题,相当于选最少的点覆盖所有区间
    int findMinArrowShots(vector<vector<int>>& points) {
        if(points.empty()) return 0;
        int n = points.size();
        sort(points.begin(),points.end(),compare);
        //记录上一个区间的右边界,最初始的为第一组数
        int pre = 0;
        int count = 0;
        for(int i=1; i<n; i++){
            if(points[i][0] > points[pre][1]){
                pre = i;
            }else{
                count++;
            }
        }
        return n - count;
    }
    static bool compare(vector<int> &a, vector<int> &b){
        return a[1] < b[1];
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/1076.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于 pytorch 的手写 transformer + tokenizer

先放出 transformer 的整体结构图,以便复习,接下来就一个模块一个模块的实现它。 1. Embedding Embedding 部分主要由两部分组成,即 Input Embedding 和 Positional Encoding,位置编码记录了每一个词出现的位置。通过加入位置编码可以提高模型的准确率,因为同一个词出现在…

Web3中文|政策影响下的新加坡Web3步伐喜忧参半

如果说“亚洲四小龙”是新加坡曾经的荣耀&#xff0c;那么当时代进入21世纪的第二个十年&#xff0c;用新加坡经济协会&#xff08;SEE&#xff09;副主席、新加坡新跃社科大学教授李国权的话来说&#xff0c;新加坡现在的“荣耀”是全球金融的主要“节点”或区块链行业发展的关…

单片机能运行操作系统吗?

先直接上答案&#xff1a;可以&#xff01;但是操作系统不是刚需&#xff0c;上操作系统比较占用单片机的资源&#xff0c;比如占用比较多的FLASH和RAM&#xff0c;间接增加了硬件成本&#xff0c;哪怕成本增加1毛钱&#xff0c;对于上量的产品&#xff0c;分分钟是一个工程师的…

【ChatGPT】论文阅读神器 SciSpace 注册与测试

【ChatGPT】论文阅读神器 SciSpace 注册与测试1. 【SciSpace】网址与用户注册1.1 官网地址&#xff1a;[【SciSpace官网】https://typeset.io](https://typeset.io)1.2 官网注册2. 【SciSpace】实战解说2.1 导入论文2.2 论文分析2.3 中文分析2.4 论文分析进阶2.5 公式表格分析3…

没有关系的话,那就去建立关系吧

今天给大家分享一道链表的好题--链表的深度拷贝&#xff0c;学会这道题&#xff0c;你的链表就可以达到优秀的水平了。力扣 先来理解一下题目意思&#xff0c;即建立一个新的单向链表&#xff0c;里面每个结点的值与对应的原链表相同&#xff0c;并且random指针也要指向新链表中…

Maven聚合开发【实例详解---5555字】

目录 一、Maven聚合开发_继承关系 二、Maven聚合案例 1. 搭建dao模块 2. 搭建service模块 3. 搭建web模块 4. 运行项目 一、Maven聚合开发_继承关系 Maven中的继承是针对于父工程和子工程。父工程定义的依赖和插件子工程可以直接使用。注意父工程类型一定为POM类型工程…

vue的diff算法?

文章目录是什么比较方式原理分析Diff算法的步骤&#xff1a;首尾指针法比对顺序&#xff1a;是什么 diff 算法是一种通过同层的树节点进行比较的高效算法 其有两个特点&#xff1a; 比较只会在同层级进行, 不会跨层级比较 在diff比较的过程中&#xff0c;循环从两边向中间比较…

2023年网络安全趋势

数据安全越来越重要。 我国《数据安全法》提出“建立健全数据安全治理体系”&#xff0c;各地区部门均在探索和简历数据分类分级、重要数据识别与重点保护制度。 数据安全治理不仅是一系列技术应用或产品&#xff0c;更是包括组织构建、规范制定、技术支撑等要素共同完成数据…

【FPGA-Spirit_V2】小精灵V2开发板初使用

&#x1f389;欢迎来到FPGA专栏~小精灵V2开发板初使用 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;FPGA学习之旅 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望大家…

Kaggle实战入门:泰坦尼克号生生还预测

Kaggle实战入门&#xff1a;泰坦尼克号生生还预测1. 加载数据2. 特征工程3. 模型训练4. 模型部署泰坦尼克号&#xff08;Titanic&#xff09;&#xff0c;又称铁达尼号&#xff0c;是当时世界上体积最庞大、内部设施最豪华的客运轮船&#xff0c;有“永不沉没”的美誉&#xff…

Spring-Kafka 发送消息的两种写法

文章目录前言写法一&#xff1a;发送的消息对象是字符串1 创建项目2 项目结构3 application.yml 配置文件4 生产者 KafkaProducerComponent5 消费者 KafkaConsumerComponent6 控制器&#xff08;GET请求发送消息&#xff09;7 启动类8 测试效果写法二&#xff1a;发送复杂消息对…

【C++】多态

文章目录多态的概念多态的定义及实现多态的构成条件虚函数虚函数的重写C11 final和override抽象类概念多态的原理&#xff08;以下演示在32平台&#xff09;虚函数表多态的原理静态绑定和动态绑定单继承和多继承关系的虚函数表单继承派生类的虚函数表多继承派生类的虚函数表其他…

彻底理解Session、Cookie、Token,入门及实战

文章目录Session Cookie的使用Token的使用Session Cookie的使用 1. Session存储数据 HttpSession session request.getSession(); //Servlet底层通过的SESSIONID&#xff0c;获取Session对象。 session.setAttribute("loginTime",new Date()); out.println(&q…

【算法基础】数据结构| 单链表+双链表 代码实现+图解+原理

博主简介&#xff1a;努力学习的预备程序媛一枚~博主主页&#xff1a; 是瑶瑶子啦所属专栏: Java岛冒险记【从小白到大佬之路】 前言 因为瑶瑶子正在备战蓝桥杯和校内ACM选拔赛&#xff0c;最近在学习算法相关的知识。我是借助AcWing网站来学习的&#xff0c;这篇文章是我学习…

1.3 K8S入门之组件说明

Borg K8S起源于Borg系统三种请求来源&#xff1a; borgcfgCLTWEB browsersBorgMaster: 负责请求的分发Borglet: 工人sheduler&#xff1a;包工头 和Persist store交互&#xff0c;不直接和Borglet交互Borglet监听Persist store K8S CS结构 Master服务器Node节点 Replicat…

行业洞察丨PDF图纸为什么影响生产企业的生产质量?订单交期?

随着现代社会科技的发展&#xff0c;在全球激烈的市场竞争下&#xff0c;国内企业基于质量和成本的竞争已经日益转化为基于时间的竞争&#xff0c;如何快速响应瞬息万变的市场需求&#xff0c;更快完成生产订单交付&#xff1f;这已成为生产型企业面临的一大痛点。 承接市场客户…

python搭建web服务器

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

用 DolphinDB 和 Python Celery 搭建一个高性能因子计算平台

因子挖掘是量化金融研究和交易的核心工作。传统的开发流程中&#xff0c;通常使用 Python 从关系型数据库&#xff08;如 SqlServer, Oracle 等&#xff09;读取数据&#xff0c;在 Python 中进行因子计算。随着证券交易规模不断扩大以及交易数据量的激增&#xff0c;用户对因子…

QT VTK开发 (一、下载编译)

Vtk&#xff0c;&#xff08;visualization toolkit&#xff09;是一个开源的免费软件系统&#xff0c;主要用于三维计算机图形学、图像处理和可视化。Vtk是在面向对象原理的基础上设计和实现的&#xff0c;它的内核是用C构建的&#xff0c;包含有大约250,000行代码&#xff0c…

计算机组成原理实验一(完整)

在VC中使用调试功能将下列语句运行的内存存放结果截图&#xff0c;每运行一句需截图一次。 #include<stdio.h> int main() {int a 你的学号末两位-100; //0x&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#x…