刷题之贪心3

news2024/11/17 12:39:02

前言

大家好,我是jiantaoyab,这篇文章将给大家介绍贪心算法和贪心算法题目的练习和解析,贪心算法的本质就是每一个阶段都是局部最优,从而实现全局最优。加上这篇文章一共有30道贪心题目了,加油!

坏了的计算器

image-20240323084010973

题目分析

image-20240323090707048

所以,只要tar<= sV,无论是奇数还是偶数都加1,当tar>sV时,奇数+1,偶数/2。

代码

class Solution {
public:
    int brokenCalc(int startValue, int target) {
      int count = 0;
      while(target > startValue)
      {
  
        if(target % 2 == 0) target /= 2;
        else target += 1;
        count++;
      }
      //剩下target <= startValue 都是+1的
      //所以startValue - target 统计出有多少个1
      return count + startValue - target;
    }
};

合并区间

image-20240323091948868

题目分析

这种问题叫区间问题,一般先排序。这里用左端点排序。

image-20240323095428846

证明:能够合并的区间都是连续的

image-20240323100506949

代码

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
      vector<vector<int>> ret;
      //排序
      sort(intervals.begin(), intervals.end());
      int left = intervals[0][0], right = intervals[0][1];
      for(int i = 0; i < intervals.size(); i++)
      {
        int l = intervals[i][0], r = intervals[i][1];
        if(l <= right)
        {
          //有重叠部分
          right = max(right, r);
        }
        else
        {
          //没有重叠部分
          ret.push_back({left, right});
          left = l;
          right = r;
        }
      }
      ret.push_back({left, right});
      return ret;

    }
};

无重叠区间

image-20240323100619988

贪心的策略如果有重叠区间就移除右断点大的区间,如果没重叠区间的话说明这个区间不会和后面的区间重叠就保留下来,接着用下一个区间去和后面的区间判断。

代码

class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        int count = 0;
        sort(intervals.begin(), intervals.end());
        int left = intervals[0][0], right = intervals[0][1];
        for(int i = 1; i < intervals.size(); i++)
        {
          int l = intervals[i][0], r = intervals[i][1];
          if(l < right) 
          {
            //有重叠部分
            count++;
            right = min(right, r);
            
          }
          else  
          {
            //没有重叠部分
            right = r;
          }
        }
        return count;
    }
};

用最少数量的箭引爆气球

image-20240325084609342

题目分析

这道题目和合并区间求的不一样,我们这里求的是交集。

image-20240325091858577

代码

class Solution {
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        sort(points.begin(), points.end());
        int n = points.size();
        int ret = 1; //默认是有一个区间去和下一个区间进行比较
        int right = points[0][1];
        for(int i = 0; i < n; i++)
        {
          int l = points[i][0], r = points[i][1];
          if(l <= right)
          {
            //有交集
            right = min(r, right);
          }
          else
          {
            //没有交集
            ret++;
            right = r;
          }
        }
        return ret;
      
    }
};

整数替换

image-20240325092631599

题目分析

image-20240325102306024

代码

贪心思想来做

class Solution {
public:
    int integerReplacement(int n) {
      int count = 0;
      while(n != 1)
      {
        if(n % 2 == 0) 
        {
          n /= 2;
          count++;
        }
        else
        {
          if(n == 3)
          {
              n = 1;
              count += 2;
          }         
          else if(n % 4 == 3) //说明是...11
          {
             n = n / 2 + 1;
             count += 2;
          }
          else //....01
          {
            count += 2;
            n /= 2;
          }

        }
      }
      return count;
    }
};

用记忆化搜索做

class Solution {
  unordered_map<int, int> hash;
public:
    int dfs(long long n)
    {
      if(hash[n]) return hash[n];
      if(n == 1)
      {
        hash[1] = 0;
        return 0;
      } 
      if(n % 2 == 0)
      {
        hash[n] = 1 + dfs(n / 2);
        return hash[n];
      }
      else
      {
        hash[n] = 1 + min(dfs(n + 1), dfs(n - 1));
        return hash[n];
      }
    }
    int integerReplacement(int n) {
      return dfs(n);
    }
};

俄罗斯套娃信封问题

image-20240325103044807

题目分析

image-20240325110947735

代码

不是很理解的可以看看第一篇贪心算法

class Solution {
public:
    int maxEnvelopes(vector<vector<int>>& envelopes) {
        sort(envelopes.begin(), envelopes.end(), [&](const vector<int>&v1, const vector<int>&v2)
        {
          return v1[0] != v2[0] ? v1[0] < v2[0] : v1[1] >  v2[1];
        });

        vector<int> ret;
        ret.push_back(envelopes[0][1]);

        for(int i = 1; i < envelopes.size(); i++)
        {
          int r = envelopes[i][1];
          if(r > ret.back())
          {
            ret.push_back(r);
          }
          else
          {
            int left = 0, right = ret.size() - 1;
            while(left < right)
            {
              int mid = (left + right) / 2;
              if(ret[mid] >= r) right = mid;
              else left = mid + 1;
            }
            ret[left] = r;
          }
        }

        return ret.size();
    }
};

可被三整除的最大和

image-20240326191035787

题目分析

image-20240326193532737

引入一个新问题,如何求出最小值和次小值

image-20240326193915292

代码

class Solution {
public:
    int maxSumDivThree(vector<int>& nums) {
       const int INF = 0x3f3f3f3f;
       int x1 = INF, x2 = INF, y1 = INF, y2 = INF;
       int sum = 0;
       for(auto x : nums)
       {
          sum += x;
          if(x % 3 == 1)
          {
            if(x < x1) 
            {
              x2 = x1;
              x1 = x;
            }
            else if(x < x2) x2 = x;
          }
          else if(x % 3 == 2)
          {
            if(x < y1)
            {
              y2 = y1;
              y1 = x;
            }
            else if(x < y2) y2 = x; 
          }
       }

       if(sum % 3 == 0) return sum;
       else if(sum % 3 == 1) return max(sum - x1, sum - y1 - y2);
       else return max(sum - y1, sum - x1 - x2);
    }
};

距离相等的条形码

image-20240326195602785

题目分析

把数字间隔1个数字放,先放次数最多的,放下的数字的顺序怎么放都可以。

证明

题目一定是有解的,那么出现最多的那个数字不能超过 n + 1 / 2次,因为如果有n个抽屉,放n + 1 个东西,必然有一个抽屉放2个,分情况讨论。

如果最多出现的数字次数刚好是 n + 1 / 2,那么剩下的随便放,都不相邻

如果出现的数字次数小于 n + 1 / 2,那更不可能相邻了,如果有相邻的说明这个数字出现的次数一定比 这个数字出现的次数多,那它就是最多出现次数的数字了,所以先放次数最多的,放下的数字的顺序怎么放都可以。

代码

class Solution {
public:
    vector<int> rearrangeBarcodes(vector<int>& barcodes) {
      unordered_map<int, int> hash;
      int n = barcodes.size();
      int max_val = 0, max_count = 0;
      for(auto x : barcodes)
      {
        if(max_count < ++hash[x])
        {
          max_val = x;
          max_count = hash[x];
        }
      }

      vector<int> ret(n);
      int index = 0;
      //先放出现次数最多的数字
      for(int i = 0; i < max_count; i++)
      {
        ret[index] = max_val;
        index += 2;
      }

      //处理剩下的数字
      hash.erase(max_val);
      for(auto& [x, y] : hash)
      {
        for(int i = 0; i < y; i++)
        {
          if(index >= n)index = 1;
           ret[index] = x;
            index += 2;
        }
      }
      return ret;
    }
};

重构字符串

image-20240326203040064

代码

这道题目和上一题的区别就是这道题目可能是没有解的。

class Solution {
public:
    string reorganizeString(string s) {
      int hash[26] = {0};
      int n = s.size();
      char max_ch = ' ';
      int max_count = 0;
      for(const auto ch : s)
      {
        if(max_count < ++hash[ch - 'a'])
        {
          max_count = hash[ch - 'a'];
          max_ch = ch;
        }
      }
      if(max_count > (n + 1) / 2 ) return "";
      string ret(n, ' ');
      int index = 0;
      //先放最多的英文
      for(int i = 0; i < max_count; i++)
      {
        ret[index] = max_ch;
        index += 2;
      }
      hash[max_ch - 'a'] = 0;
      //放剩下的英文
     for(int i = 0; i < 26; i++)
     {
        for(int j = 0; j < hash[i]; j++)
        {
          if(index >= n) index = 1;
          ret[index] = 'a' + i;
          index += 2;
        }
     }
      return ret;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

改造 cl_demo_output=>display支持第一行字段名显示成字段描述

1.背景: 标准的cl_demo_output=>display显示的内表第一行为字段名,不方便用户查看,故需要将第一行换成字段描述 2.方法: 2.1 建立FIELDCAT字段结构 定义包含字段名和字段描述的结构和行类型 2.2 建立类,编写相关代码 代码如下: DATA type TYPE c LENGTH 1. DAT…

怎么创建百科人物的词条?百度百科词条创建

百度百科中&#xff0c;创建一个属于自己的词条&#xff0c;不仅是个人荣誉的象征&#xff0c;更是对其生平事迹的官方记录&#xff0c;能够让更多人了解和记住一个人的成就。那么&#xff0c;如何创建一个高质量的百科人物词条呢&#xff1f;本文伯乐网络传媒将详细解答这一问…

007_how_to_start_learning_Matlab学习的启动与加速

Matlab学习的启动与加速 1. 前言 这个专题的Matlab博文系列&#xff0c;来到了传奇的007&#xff0c;我又准备放下技术工作的写作&#xff0c;来一点务虚和规划的内容。 这个系列的开始&#xff0c;也是一个随机发生的小概率事件&#xff0c;本来Python&#xff08;PyQt&…

【MySQL】多版本并发控制

一、什么是MVCC MVCC是通过数据行的多个版本管理来实现数据库的并发控制。MVCC也就相当于是如何实现在相应的隔离级别下&#xff0c;更好的实现并发。 二、快照读与当前写 MVCC在InnoDB中的实现主要是为了提高数据库并发性能&#xff0c;用更好的方式去处理读-写冲突。 2.1、…

软件应用实例,租赁系统软件操作教程,脚手架租赁管理集装箱租赁管理系统教程

软件应用实例&#xff0c;租赁系统软件操作教程&#xff0c;脚手架租赁管理集装箱租赁管理系统教程 一、前言 以下软件操作教程以&#xff0c;佳易王租赁管理系统软件V17.0为例说明 件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、软件可以记录&#x…

MySQL索引优化实战宝典

MySQL索引是MySQL数据库用于快速查找和访问数据的一种数据结构&#xff0c;它就像书的目录一样&#xff0c;可以帮助数据库系统更快地定位到所需数据的位置&#xff0c;从而大大提高查询性能。 下面来看一下索引分类 一、索引分类 本文介绍平时使用最多的基于 InnnoDB…

盘点4款最适合教学的电路仿真软件

在现代电子教育中&#xff0c;电路仿真软件扮演着至关重要的角色。它们不仅能够帮助学生更好地理解电子电路原理&#xff0c;还能够提升教学效率&#xff0c;培养学生的实践能力。本文将盘点4款最适合教学的电路仿真软件&#xff0c;助您选择最佳的教学利器&#xff0c;同时介绍…

HTTP的三次握手和四次挥手? 我都给你讲清楚 !!!

今天我们来聊聊一个计算机网络中非常基础但又非常重要的概念——HTTP的三次握手和四次挥手。 一、三次握手 首先&#xff0c;我们来聊聊三次握手。三次握手其实是TCP&#xff08;传输控制协议&#xff09;建立连接时的一个过程&#xff0c;而HTTP是基于TCP的&#xff0c;所以我…

centos 环境部署

一、安装redis 1. 升级 GCC 最直接的解决方式是升级你的 GCC 编译器到支持 C11 标准的版本。CentOS 7 默认的 GCC 版本较旧&#xff0c;可能不支持 _Atomic。你可以通过以下步骤升级 GCC&#xff1a; 启用 CentOS 的 Software Collections (SCL) 仓库&#xff0c;该仓库提供了…

学习使用xbox手柄控制小乌龟节点移动

使用xbox手柄控制小乌龟&#xff0c;首先要下载joy功能包&#xff0c;发布sensor_msgs话题也就是手柄和ros通信的话题。 下载的步骤就根据官方文档即可 joy/Tutorials/ConfiguringALinuxJoystick - ROS Wiki 这里我提供一下具体步骤 第一步 安装joy 首先安装对应系统版本的…

Oracle VM(虚拟机)性能监控工具

Oracle VM是一个独立的虚拟化环境&#xff0c;由 Oracle 提供支持和设计&#xff0c;旨在为运行虚拟机提供轻量级、安全的基于服务器的平台。Oracle VM 能够在受支持的虚拟化环境中部署操作系统和应用软件&#xff0c;Oracle VM 将用户和管理员与底层虚拟化技术隔离开来&#x…

Java Web-Tomcat

Web服务器 Web服务器是一个软件程序,对HTTP协议的操作进行封装,使得程序员不必直接对协议进行操作,让Web开发更加便捷。主要功能是“提供网上信息浏览服务”。 Tomcat&#xff0c;是一个 HTTP 服务器。我们只需要在服务器中安装一个Web服务器如Tomcat&#xff0c;然后就可以将…

vue项目使用eletron将打包成桌面应用(.exe)

vue项目使用eletron将打包成桌面应用(.exe) 1.前期准备 两个项目&#xff1a; 1、自己用vue cli创建的项目 2、第二个是去gitee将案例clone下来 案例地址 https://gitee.com/qingplus/electron-quick-start.git 2、测试案例是否可以正常运行 # 进入项目 cd electron-quick-…

考研数学|《1800》《1000》《880》《660》最佳搭配使用方法

直接说结论&#xff1a;基础不好先做1800、强化之前660&#xff0c;强化可选880/1000题。 首先&#xff0c;传统习题册存在的一个问题是题量较大&#xff0c;但难度波动较大。《汤家凤1800》和《张宇1000》题量庞大&#xff0c;但有些题目难度不够平衡&#xff0c;有些过于简单…

TinyEMU源码分析之启动流程

TinyEMU源码分析之启动流程 1 始于0x10002 确定BBL入口点3 mentry.S执行过程4 启动流程小结 本文属于《 TinyEMU模拟器基础系列教程》之一&#xff0c;欢迎查看其它文章。 本文中使用的代码&#xff0c;均为伪代码&#xff0c;删除了部分源码。 1 始于0x1000 我们沿着TinyEMU…

夜晚水闸3D可视化:科技魔法点亮水利新纪元

在宁静的夜晚&#xff0c;当城市的霓虹灯逐渐暗淡&#xff0c;你是否曾想过&#xff0c;那些默默守护着城市安全的水闸&#xff0c;在科技的魔力下&#xff0c;正焕发出别样的光彩&#xff1f;今天&#xff0c;就让我们一起走进夜晚水闸3D模型&#xff0c;感受科技为水利带来的…

AI足球教练上岗利物浦,射门机会提高13%!来自DeepMind,网友:这不公平

梦晨 发自 凹非寺 量子位 | 公众号 QbitAI AI足球教练登上Nature子刊&#xff0c;谷歌DeepMind与利物浦队合作三年打造&#xff1a; 如同AlphaGo颠覆围棋一样&#xff0c;改变了球队制定战术的方式。 像是进攻方把球传给谁更容易创造射门机会&#xff0c;防守方如何调整布阵……

【双指针】Leetcode 四数之和

题目解析 18. 四数之和 这道题的思路和三数之和的思路相同&#xff0c;都是固定一个数&#xff0c;然后在剩下的区间中寻找和为目标值的元组&#xff0c;其次最重要的是要进行去重 算法讲解 1. 完成排序 2. 固定一个数&#xff0c;求剩下区间中三元组的和等于 target - nums[…

用易查分制作承诺书签订,在线手写签名,一键导出打印

假期将至&#xff0c;为积极落实安全管理规定&#xff0c;单位通常需要下发安全承诺书进行签字确认。 易查分可以实现网上下发安全承诺书通知&#xff0c;让查询者进行签名确认&#xff0c;还可以生成PDF&#xff0c;方便打印一人一张的纸质版承诺书&#xff0c;本次就来介绍如…

flask各种版本的项目,终端命令运行方式的实现

目录 写在前面 一、Flask项目的基本结构 二、使用终端命令运行Flask项目 1. 安装Flask 2. 创建Flask应用 3. 配置FLASK_APP环境变量 4. 运行Flask应用 5. 访问Flask应用 三、Flask CLI的其他功能 1. 创建Flask应用 2. 运行开发服务器 3. 清理缓存文件 4. 运行单元…