c# 贪心算法(Greedy Algo)

news2024/9/24 17:17:24

        贪婪是一种算法范式,它逐步构建解决方案,始终选择提供最明显和直接收益的下一个部分。贪婪算法用于解决优化问题。 

如果问题具有以下属性,则可以使用贪心法解决优化问题: 

        每一步,我们都可以做出当前看来最好的选择,从而得到整个问题的最优解。 

        如果贪婪算法可以解决某个问题,那么它通常会成为解决该问题的最佳方法,因为贪婪算法通常比动态规划等其他技术更有效。但贪婪算法并不总是适用。例如,Fractional Knapsack问题可以使用Greedy来解决,但是0-1 Knapsack问题不能使用Greedy来解决。

以下是一些贪婪算法的标准算法:

1)Kruskal的最小生成树(MST): 
        在 Kruskal 算法中,我们通过一条一条地选取边来创建 MST。贪心选择是选择在目前构建的 MST 中不会引起循环的最小权重边

2)Prim的最小生成树: 
        在 Prim 的算法中,我们也是通过逐条选取边来创建 MST。我们维护两个集合:一组已包含在 MST 中的顶点和一组尚未包含的顶点。贪心选择是选择连接两个集合的最小权重边

3)Dijkstra的最短路径: 
        Dijkstra 算法与 Prim 算法非常相似。最短路径树是逐边构建的。我们维护两个集合:一组已包含在树中的顶点和一组尚未包含的顶点。贪心选择是选择连接两个集合并且位于从源到包含尚未包含的顶点的集合的最小权重路径上的边

4)霍夫曼编码: 
        霍夫曼编码是一种无损压缩技术。它将可变长度位代码分配给不同的字符。贪心选择是将最小位长的代码分配给最常见的字符。

        贪心算法有时也用于获得硬优化问题的近似值。例如,旅行商问题是一个 NP 难问题。这个问题的贪婪选择是每一步都选择距离当前城市最近的未访问过的城市。这些解决方案并不总是产生最佳的最优解决方案,但可用于获得近似最优的解决方案。

这里让我们看一个可以使用贪心算法解决的问题

问题:
        您将获得n项活动及其开始和结束时间。选择一个人可以执行的最大活动数,假设一个人一次只能从事一项活动。 

例子:  

输入: start[] = {10, 12, 20}, finish[] = {20, 25, 30}
输出: 0
解释:一个人最多可以执行一项活动。

输入: start[] = {1, 3, 0, 5, 8, 5}, finish[] = {2, 4, 6, 7, 9, 9};
输出: 0 1 3 4
解释:一个人最多可以执行四项活动。
可以执行的最大活动集 是 
{0, 1, 3, 4} [ 这些是 start[] 和 finish[] 中的索引

方法:要解决该问题,请遵循以下想法:

        贪心选择是总是选择剩余活动中完成时间最短的下一个活动,并且开始时间大于或等于先前选择的活动的结束时间。我们可以根据活动的完成时间对活动进行排序,以便我们始终将下一个活动视为完成时间最短的活动

请按照给定的步骤解决问题:

1、根据活动的完成时间对活动进行排序 
2、从排序数组中选择第一个活动并打印它 
3、对排序数组中的剩余活动执行以下操作
4、如果此活动的开始时间大于或等于先前选择的活动的结束时间,则选择此活动并打印
注意:在实现中,假设活动已经按照完成时间排序,否则时间复杂度将上升到 O(N*log(N)),辅助空间将上升到 O(N),因为我们必须创建一个二维数组来将开始时间和结束时间存储在一起。

下面是上述方法的实现。

// C# program for activity selection problem. 
  
// The following implementation assumes 
// that the activities are already sorted 
// according to their finish time 
using System; 
  
class GFG { 
    // Prints a maximum set of activities 
    // that can be done by a single 
    // person, one at a time. 
    public static void printMaxActivities(int[] s, int[] f, 
                                          int n) 
    { 
        int i, j; 
  
        Console.Write( 
            "Following activities are selected\n"); 
  
        // The first activity always gets selected 
        i = 0; 
        Console.Write(i + " "); 
  
        // Consider rest of the activities 
        for (j = 1; j < n; j++) { 
            // If this activity has start time greater than 
            // or equal to the finish time of previously 
            // selected activity, then select it 
            if (s[j] >= f[i]) { 
                Console.Write(j + " "); 
                i = j; 
            } 
        } 
    } 
  
    // Driver Code 
    public static void Main() 
    { 
        int[] s = { 1, 3, 0, 5, 8, 5 }; 
        int[] f = { 2, 4, 6, 7, 9, 9 }; 
        int n = s.Length; 
  
        // Function call 
        printMaxActivities(s, f, n); 
    } 

  
// This code is contributed 
// by ChitraNayal 

输出
选择以下活动
0 1 3 4
时间复杂度: O(N)
辅助空间: O(1)

贪婪选择如何适用于根据完成时间排序的活动? 
        假设给定的活动集为 S = {1, 2, 3, …n},活动按完成时间排序。贪婪选择总是选择活动 1。为什么活动 1 总是提供最佳解决方案之一?

        我们可以通过证明如果存在另一个解 B 且第一个活动不是 1,则也存在一个与活动 1 大小相同的解 A 作为第一个活动。设B选择的第一个活动为k,则总存在A = {B – {k}} U {1}。

注: B 中的活动是独立的,并且 k 的完成时间是所有活动中最小的。由于 k 不为 1,所以 finish(k) >= finish(1))

当给定的活动未排序时如何实施? 
        我们为活动创建一个结构/类。我们按完成时间对所有活动进行排序(请参阅C++ STL 中的排序)。一旦我们对活动进行排序,我们就应用相同的算法。

下图是上述方法的说明: 

 下面是上述方法的实现:

// C# program for activity selection problem 
// when input activities may not be sorted. 
using System; 
using System.Collections.Generic; 
using System.Linq; 
  
// A job has a start time, finish time and profit. 
class Activity { 
  public int start, finish; 
  
  // Constructor 
  public Activity(int start, int finish) 
  { 
    this.start = start; 
    this.finish = finish; 
  } 

  
  
// Driver class 
class GFG { 
  
  // Returns count of the maximum set of activities that 
  // can 
  // be done by a single person, one at a time. 
  static void printMaxActivities(List<Activity> arr, int n) 
  { 
    // Sort jobs according to finish time 
    arr = arr.OrderBy(a => a.finish).ToList(); 
    Console.WriteLine( 
      "Following activities are selected :"); 
  
  
  
    // The first activity always gets selected 
    int i = 0; 
    Console.Write("(" + arr[i].start + ", "
                  + arr[i].finish + ")"); 
  
    // Consider rest of the activities 
    for (int j = 1; j < n; j++) { 
  
      // If this activity has start time greater than 
      // or equal to the finish time of previously 
      // selected activity, then select it 
      if (arr[j].start >= arr[i].finish) { 
        Console.Write(", (" + arr[j].start + ", "
                      + arr[j].finish + ")"); 
        i = j; 
      } 
    } 
  } 
  
  // Driver code 
  public static void Main(string[] args) 
  { 
  
    int n = 6; 
    List<Activity> arr = new List<Activity>(); 
    arr.Add(new Activity(5, 9)); 
    arr.Add(new Activity(1, 2)); 
    arr.Add(new Activity(3, 4)); 
    arr.Add(new Activity(0, 6)); 
    arr.Add(new Activity(5, 7)); 
    arr.Add(new Activity(8, 9)); 
  
  
    // Function call 
    printMaxActivities(arr, n); 
  } 

  
// This code is contributed by phasing17 

输出
选定以下活动:
(1、2)、(3、4)、(5、7)、(8、9)
时间复杂度: O(N log N),如果输入活动可能无法排序。当输入活动始终排序时,需要 O(n) 时间。
辅助空间: O(1)

使用优先级队列的活动选择问题:
我们可以使用 Min-Heap 来获取完成时间最短的活动。Min-Heap 可以使用优先级队列实现

请按照给定的步骤解决问题:

1、创建优先级队列(最小堆)并将活动推入其中。
2、将优先级队列的顶部推入答案向量,并将变量start设置为第一个活动的开始时间,将变量end 3、设置为该活动的结束时间
4、当优先级不为空时,执行以下操作:
        4.1、取出优先级队列的顶部并检查
        4.2、如果此活动的开始时间大于或等于最后选择的活动的结束时间,则将此活动推入答案向量
        4.3、不然就忽略它
 5、打印选择的活动,存储在答案向量中

下面是上述方法的实现:

// C# program for activity selection problem 
// when input activities may not be sorted. 
using System; 
using System.Linq; 
using System.Collections.Generic; 
  
class GFG 

  static void SelectActivities(List<int> s, List<int> f) 
  { 
    // List to store results. 
    List<Tuple<int, int> > ans = new  List<Tuple<int, int> >(); 
  
    // Minimum Priority Queue to sort activities in 
    // ascending order of finishing time (f[i]). 
  
    var p = new List<Tuple<int, int>>(); 
  
    for (int i = 0; i < s.Count; i++) { 
      // Pushing elements in priority queue where the key 
      // is f[i] 
      p.Add(Tuple.Create(f[i], s[i])); 
    } 
    p.Sort(); 
  
    var it = p[0]; 
    int start = it.Item2; 
    int end = it.Item1; 
    p.RemoveAt(0); 
    ans.Add(Tuple.Create(start, end)); 
  
    while (p.Count > 0) { 
  
      var itr = p[0]; 
      p.RemoveAt(0); 
      if (itr.Item2 >= end) { 
        start = itr.Item2; 
        end = itr.Item1; 
        ans.Add(Tuple.Create(start, end)); 
      } 
    } 
    Console.Write("Following Activities should be selected.\n\n"); 
  
    foreach (var itr in ans) 
      Console.Write("Activity started at " + itr.Item1 
                    + " and ends at " + itr.Item2 + "\n"); 
  } 
  
  // Driver code 
  public static void Main(string[] args) 
  { 
    List<int> s = new List<int>  { 1, 3, 0, 5, 8, 5 }; 
    List<int> f = new List<int> { 2, 4, 6, 7, 9, 9 }; 
  
    // Function call 
    SelectActivities(s, f); 
  
  } 

  
// This code is contributed by phasing17. 

输出
应选择以下活动。

活动开始于:1 结束于:2
活动开始于:3 结束于:4
活动开始于:5 结束于:7
活动开始于:8 结束于:9
时间复杂度: O(N * log N)
辅助空间: O(N)

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

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

相关文章

Spring Cloud Alibaba 架构-Sentinel熔断降级

Sentinel主要功能 Sentinel 是阿里巴巴开源的一款流量控制、熔断降级组件&#xff0c;它主要用于保护微服务系统。Sentinel 的主要功能包括以下几个方面&#xff1a; 1. 流量控制&#xff08;Flow Control&#xff09;&#xff1a; Sentinel 通过控制并发请求的数量或速率&am…

【Python】搭建pypi私仓

1. 下载依赖 pip install pypiserver # 命令安装 pypiserver 库 pip install passlib # passlib 包来读取 Apache htpasswd 文件apt-get install -y apache2-utils2. 生成密码 使用htpasswd库在指定路径/path/to/.pypipasswd生成密码文件 htpasswd -c /path/to/.pypipasswd …

Windows64位操作系统安装汇编语言环境

1、下载好MASM工具, 并存放在指定路径 2、再安装一个DOSBox 3、打开DOSBox, 并使用 mount 将刚刚存放MASM的路径挂在到C盘&#xff0c;然后进入C盘就可以使用 MASM的命令工具了。 例如&#xff1a; mount c G:\install\study\MASM C:但是DOSBox默认打开的窗口是很小的&…

Jenkins配置(插件/角色/凭证)

目录 传送门前言一、Jenkins插件管理1、更换为国内下载源2、中文汉化插件下载&#xff08;不推荐&#xff09;3、低版本Jenkins爆红插件安装4、低版本Jenkins插件持续报错解决办法 二、Jenkins用户角色三、Jenkins凭证管理&#xff08;svn/git&#xff09;1、Username with pas…

Linux的nload/nettraf命令实时网卡流量监测

对于linux的网卡上下行流量监测方法有很多 例如nload 现成的nload命令 现成的有 nload 安装 yum -y install nload 查看所有网卡实时网速 sudo nload -m 按enter/上下翻页键即可切换网卡 查看指定网卡实时网速 sudo nload eth0 -m 基于nettraf编译的rpm包 当然也可以你…

Java计算日期相差天数的几种方法

Java计算日期相差天数的几种方法 &#x1f5d3;️ Java计算日期相差天数的几种方法摘要引言一、使用java.util.Date和java.util.Calendar&#x1f4c5;1. 使用java.util.Date示例代码 2. 使用java.util.Calendar示例代码 二、使用java.time.LocalDate&#x1f4c6;示例代码 三、…

这13个前端库,帮我在工作中赢得了不少摸鱼时间

前言 平时开发的过程中&#xff0c;常常会使用到一些第三方库来提高开发效率&#xff0c;我总结了自己工作这么久以来经常用到的 13 个库&#xff0c;希望对大家有帮助&#xff5e; antd 全称应该是Ant Design&#xff0c;这是一个 React 的组件库&#xff0c;旨在提供一套常…

基于springboot实现中国陕西民俗网系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现中国陕西民俗网系统演示 摘要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱&#xff0c…

内网安全--域渗透准备知识

目录 知识点&#xff1a; 0x01 0x02 0x03 系列点&#xff1a; Linux主机信息收集 windows主机信息收集 知识点&#xff1a; 0、域产生原因 1、内网域的区别 2、如何判断在域内 3、域内常见信息收集 4、域内自动化工具收集 -局域网&工作组&域环境区别 -域…

第一节:Redis的数据类型和基本操作

最近整理了关于Redis的一些文档&#xff0c;分享给大家&#xff0c;后续会持续更新...... Redis的数据类型 字符串String String&#xff1a;字符串&#xff0c;可以存储String、Integer、Float型的数据&#xff0c;甚至是二进制数据&#xff0c;一个字符串最大容量是512M 列表…

我理解的“财富真相”……

我理解的“财富真相” 人生富贵一途&#xff0c;年轻时会认为钱特别重要&#xff0c;因为要啥没啥&#xff0c;所以整台好车&#xff0c;或有个安乐窝基本是极限目标理解&#xff0c;其实也想有更多钱&#xff0c;但往远了说就具体目标模糊了&#xff0c;咬牙切齿的谈理想&…

618购物节值得入手哪些数码?值得入手的宝藏数码好物安利!

随着618购物节的到来&#xff0c;数码爱好者们纷纷摩拳擦掌&#xff0c;期待在这个年中大促中寻觅到心仪的数码好物&#xff0c;那么在这个618购物节&#xff0c;有哪些数码产品值得我们入手呢&#xff1f;接下来&#xff0c;就让我们一起盘点那些值得入手的宝藏数码好物吧&…

靠AI创意,变现20w!

文章首发于公众号&#xff1a;X小鹿AI副业 大家好&#xff0c;我是程序员X小鹿&#xff0c;前互联网大厂程序员&#xff0c;自由职业2年&#xff0c;也一名 AIGC 爱好者&#xff0c;持续分享更多前沿的「AI 工具」和「AI副业玩法」&#xff0c;欢迎一起交流~ 之前X小鹿一直在各…

注册表Windows兼容性设置(AppCompatFlags)

属性 - 兼容性 EXE文件属性中有兼容性标签&#xff0c;当有些老版本软件不能正常运行时经常会调整这里的设置。 image.png 上面的所有选项都写在注册表中&#xff0c;其中“更改所有用户的设置”保存在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppC…

一步步实现知乎热榜采集:Scala与Sttp库的应用

背景 在大数据时代&#xff0c;网络爬虫技术发挥着不可或缺的作用。它不仅能够帮助我们快速地获取互联网上的信息&#xff0c;还能处理和分析这些数据&#xff0c;为我们提供深刻的洞察。知乎&#xff0c;作为中国领先的问答社区&#xff0c;汇聚了各行各业的专家和广大用户的…

Selenium探险家:驾驭Web自动化的秘籍与实战

Hi&#xff0c;我是阿佑&#xff0c;今天将带大伙们学会如何使用Selenium进行高效的网站测试&#xff0c;如何配置Selenium Grid实现分布式测试&#xff0c;以及如何预测和拥抱自动化测试的未来&#xff01; 文章目录 1. 引言2. 背景介绍2.1 Selenium概览2.2 Python与Selenium的…

力扣刷题--268. 丢失的数字【简单】

题目描述&#x1f357; 给定一个包含 [0, n] 中 n 个数的数组 nums &#xff0c;找出 [0, n] 这个范围内没有出现在数组中的那个数。 示例 1&#xff1a; 输入&#xff1a;nums [3,0,1] 输出&#xff1a;2 解释&#xff1a;n 3&#xff0c;因为有 3 个数字&#xff0c;所以…

YOLOv5 | 卷积模块 | 提高网络的灵活性和表征能力的动态卷积【附代码+小白可上手】

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 轻量级卷积神经网络由于其低计算预算限制了CNNs的深度&#xff08;卷积层数&#xff09;和宽度&#xff08;通道数&#xff09;&#xff0c;…

广义线性chirplet变换【附MATLAB代码】

文章来源&#xff1a;微信公众号&#xff1a;EW Frontier 摘要 时频分析方法是一种刻画信号时变特征的有效工具&#xff0c;在相当长的一段时间内受到了广泛的关注。随着TF算法的发展&#xff0c;许多先进的方法被提出&#xff0c;可以提供更精确的TF结果。但是&#xff0c;不…

第一届 长城杯 总决赛wp

第一届 长城杯 总决赛 - Ahisec 第一阶段 Zip_guessinteger 第一层bkcrack攻击部分明文&#xff0c;注意偏移 ​ ┌──(root㉿Ten)-[~/tools/Misc/bkcrack] └─# ./bkcrack -C zip_guessinteger.zip -c breakthroughentry.txtflag.txt.zip -p 1.txt -o 30 bkcrack 1.6.1 …