【算法思维】-- 贪心算法

news2024/11/25 0:48:37

OJ须知:

  • 一般而言,OJ在1s内能接受的算法时间复杂度:10e8 ~ 10e9之间(中值5*10e8)。在竞赛中,一般认为计算机1秒能执行 5*10e8 次计算
时间复杂度取值范围
o(log2n)大的离谱
O(n)10e8
O(nlog(n))10e6
O(nsqrt(n)))10e5
O(n^2)5000
O(n^3)300
O(2^n)25
O(3^n)15
O(n!)

11

时间复杂度排序:o(1) < o(log2n) < o(n) < o(nlog2n) < o(n^2) < o(n^3) < o(2^n) < o(2^n) < o(3^n) < o(n!)


目录

算法思想

算法局限性

过程

案例

平衡分割字符串⭐

方法一:贪心

复杂度分析

买股票的最佳时机2⭐⭐

方法一:贪心 

复杂度分析

跳跃游戏⭐⭐

方法一:贪心(nums[i] == 0为核心)

复杂度分析

方法二:贪心(nums[i]为核心)


算法思想

        贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

融汇贯通的理解:

        贪心算法是不会考虑全局的,其每一步都会确定当前其所看到的场景下的最优的一个解  —— 整个贪心问题的解:每一步的最优解叠加之后的结果。

        有一个概念,就叫做最优子结构:每一个子问题,其的最优解最终叠加之后,能够作为最终问题的解,那就是最优子结构

融汇贯通的理解:

        所以,如果想用贪心算法,首先就要去确定一下,这个问题是不是最优子结构(将问题进行一定的缩小,查看缩小版是否符合最优子结构

算法局限性

        用贪心算法的时候,其如果不是一个最优子结构,那我们得到的这一个解,其不一定是全局的一个最优解,有可能是一个局部的最优解。

  • 不能保证求得的最后解是最佳的
  • 不能用来求最大值最小值的问题
  • 只能求满足某些约束条件可行解的范围比

过程

  1. 建立数学模型来描述问题
  2. 把求解的问题分成若干个子问题
  3. 对每一子问题求解,得到子问题的局部最优解
  4. 把子问题的局部最优解合成原来解问题的一个解

        说白了就是:假设一个问题比较复杂,暂时找不到全局最优解,那么我们可以考虑把原问题拆成几个小问题(分而治之的思想),分别求每个小问题的最优解,再把这些 “局部最优解” 叠起来,就 “当作” 整个问题的最优解了。

案例

        在我们排序所学知识中,选择排序就很好的诠释了贪心算法的使用。

        其每一次的排序都是选择未排序的区间内的最小值。 所以这个地方每一个子问题,其的最优解最终叠加之后,能够作为最终问题的解,所以是一个最优子结构

//直接插入排序
// 对比 插入排序,谁更小。
void SelectSort(int* a, int n)
{
	assert(a);
	int begin_i = 0, end_i = n - 1;
	while (begin_i < end_i)
	{
        // 贪心算法: 每次从未排序数组中找到最小值
		int min_i = begin_i;
		for (int i = begin_i + 1; i <= end_i; ++i)
		{
			if (a[i] < a[min_i])
				min_i = i;
		}

		Swap(&a[begin_i], &a[min_i]);
		++begin_i;
	}
}

        贪心算法:每次找当前情况的最优解,不用考虑上一步是什么 / 下一步是什么。

平衡分割字符串⭐

1221. 分割平衡字符串 - 力扣(LeetCode)


平衡字符串 中,'L' 和 'R' 字符的数量是相同的。

给你一个平衡字符串 s,请你将它分割成尽可能多的子字符串,并满足:

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

提示:

  • 2 <= s.length <= 1000
  • s[i] = 'L' 或 'R'
  • s 是一个 平衡 字符串

方法一:贪心

抽象题中线索:

  • 整体策略:不能让平衡字符串嵌套
  • 当前情况决策:当前情况下的字符串,是否符合平衡分割字符串
class Solution {
public:
    int balancedStringSplit(string s) {
        int ret = 0;
        int balance = 0;
        for(auto ch : s)
        {
            // 当前情况决策: 当前情况下的字符串,是否符合平衡分割字符串
            ch == 'L' ? balance++ : balance--;
            if(balance == 0) ret++;
        }
        return ret;
    }
};

复杂度分析

  • 时间复杂度:O(n)。
  • 空间复杂度:O(1)。

买股票的最佳时机2⭐⭐

122. 买卖股票的最佳时机 II


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

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

也可以先购买,然后在 同一天 出售。

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

提示:

  • 1 <= prices.length <= 3 * 10e4
  • 0 <= prices[i] <= 104

方法一:贪心 

抽象题中线索:

  • 整体策略:不能股票的购买售出嵌套
  • 当前情况决策:当前情况下的股票以最低价买入,然后以高价售出

就是判断趋势:

  • 连续上涨:上涨的最低点买入,上涨的最高点卖出 —— 上涨区间中买卖绝对利润相同。
  • 连续下跌:不进行买卖。
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int profit = 0;
        int buy = prices[0];
        int sell = 0;
        for(int i = 1; i < prices.size(); i++)
        {
            // 判断趋势
            if(prices[i] > prices[i - 1]) profit += prices[i] - prices[i - 1];
        }
        return profit;
    }
};

复杂度分析

  • 时间复杂度:O(n)。
  • 空间复杂度:O(1)。

跳跃游戏⭐

55. 跳跃游戏 - 力扣(LeetCode)


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

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

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

提示:

  • 1 <= nums.length <= 3 * 10e4
  • 0 <= nums[i] <= 105

方法一:贪心(nums[i] == 0为核心

抽象题中线索:

  • 整体策略:不要嵌套nums[i] == 0。
  • 当前情况决策:当前情况下有nums[i] == 0,其前面的最大值是否跨的过

需要注意:最后一个数据为0,不用提出,已经到最后了。

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int max = 0;
        for(int i = 0; i < nums.size() - 1; i++)
        {
            // 当前情况决策: 当前情况下有nums[i] == 0,其前面的最大值是否跨的过
            if(nums[i] + i > max) max = nums[i] + i;
            if(nums[i] == 0)
                if(max > i) 
                    continue;
                else 
                    return false;
        }
        return true;
    }
};

        max_i 位置很有可能已经完全足够到达最后,所以我们可以增加以一次判断。

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int max_i = 0;
        for(int i = 0; i < nums.size() - 1; i++)
        {
            // 当前情况决策: 当前情况下有nums[i] == 0,其前面的最大值是否跨的过
            if(nums[i] + i > max_i)
                if((max_i = nums[i] + i) >= nums.size() - 1) return true;
            if(nums[i] == 0)
                if(max_i > i) 
                    continue;
                else 
                    return false;
        }
        return true;
    }
};

复杂度分析

  • 时间复杂度:O(n)。
  • 空间复杂度:O(1)。

方法二:贪心(nums[i]为核心

抽象题中线索:

  • 整体策略:不要嵌套nums[i + 1]。
  • 当前情况决策:当前位置 i 前述最大值是否可以到达。
class Solution {
public:
    bool canJump(vector<int>& nums) {
        int max_i = 0;
        for(int i = 0; i < nums.size(); i++)
        {
            // 当前情况决策: 当前位置 i 前述最大值是否可以到达。
            if(max_i >= i)
            {
                max_i = max(max_i, nums[i] + i);
                // max_i 位置已经完全足够到达最后
                if(max_i >= nums.size() - 1) return true;
            }
            else return false;
        }
        return true;
    }
};

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

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

相关文章

LinuxC编程——标准IO

目录 标准I/O一、概念二、特点⭐⭐⭐三、缓冲区⭐⭐⭐3.1 全缓冲3.1 行缓冲3.3 不缓冲 四、函数接口⭐⭐⭐⭐4.1 打开4.1.1 fopen4.1.2 freopen4.1.2 容错机制perror 4.2 关闭4.2.1 fclose4.3 读写操作4.3.1 字符I/O4.3.2 行I/O4.3.3 块I/O 4.4 定位操作4.5 文件结束和错误 脑图…

Redis高级数据结构之HyperLogLog

HyperLogLog的介绍 这并不是一种全新的数据结构、实际类型是一种字符串类型。通过一种基数&#xff08;不重复的元素数量就是基数&#xff09;算法&#xff0c;便可以使用很小的内存空间完成独立总数的统计。数据集可以是IP、Email、ID等官方给出的统计误差是0.81%&#xff0c…

python文本注释数学表达式设置|python绘图中的数学表达式设置

本篇文章将介绍如何在Matplotlib中设置文本、注释和数学表达式&#xff0c;以便更好地呈现数据&#xff0c;提高可视化效果。 文章目录 一、Matplotlib中的文本设置1.1 纯文本设置1.2 含箭头的文本设置 二、Matplotlib中的数学表达式设置三、Matplotlib中的字体设置 一、Matplo…

Vue项目中通过插件pxtorem实现大屏响应式

一、原理 rem单位代表的是根节点的font-size大小&#xff0c;所以当我们在页面上使用rem去替代px的时候&#xff0c;就可以通过修改根节点font-size的值&#xff0c;动态地让页面上的元素根据不同浏览器宽高下去实现变化。 二、工具 1.postcss-pxtorem 作用&#xff1a;在编…

Spring Boot Application.properties和yaml配置文件

文章目录 一、全局配置文件概述二、Application.properties配置文件&#xff08;一&#xff09;创建Spring Boot的Web项目PropertiesDemo&#xff08;二&#xff09;在应用属性文件里添加相关配置1、配置服务器端口号和web虚拟路径2、对象类型的配置与使用&#xff08;1&#x…

微应用如何实现自动更新提示

首先, 先讲一下本次文章所讲的场景, 经过调研, 公司内部使用后台, 当有需求功能迭代的时候, 通常使用者会没有感知, 使用者只会在浏览器内一直打开这个页面, 当需要使用的时候, 再切换这个tab来使用. 这就导致使用者一直不知道系统更新了, 一直没有访问最新的页面(由于最新页面…

日志框架——Log4j2

日志框架——Log4j2 日志框架Log4j21. 概述2. Log4j2主要由几个重要的组件构成:3.项目中使用3.1 引入相关依赖pom.xml3.2 加入日志配置文件src/main/resources/log4j2.xml3.3 测试 日志框架Log4j2 1. 概述 Apache Log4j2是一个开源的日志记录组件&#xff0c;使用非常的广泛。…

【Protobuf速成指南】什么是Protobuf?

文章目录 一、序列化和反序列化1.1 概念1.2 场景1.3 如何序列化 二、Protobuf介绍1. 自身特点2.使用特点 一、序列化和反序列化 1.1 概念 &#x1f3af;[总结]: 序列化&#xff1a;把对象转换为字节序列的过程称为对象的序列化。反序列化&#xff1a;把字节序列恢复为对象的过…

MySQL数据库 8.DML操作

目录 ​编辑 &#x1f914;前言&#xff1a; &#x1f914;DML介绍&#xff1a; &#x1f914;语法详情&#xff1a; &#x1f600;1.插入数据&#xff1a; 特点&#xff1a; 1.给指定字段添加数据&#xff1a; 代码示例: 运行结果&#xff1a; 2.给所有的字段添加数据&…

好的用户体验和性能:现代前端的双赢之路

部分数据来源&#xff1a;ChatGPT 引言 随着 Web 应用程序的复杂度和重要性逐渐上升&#xff0c;前端开发人员已经开始更加注重应用程序的可用性和性能。在这个快速变化的时代&#xff0c;前端开发是日益增长的一个领域。 在当前的前端领域&#xff0c;用户体验和性能是前端开…

解决在谷歌浏览器下载时文件名包含逗号导致页面显示网页不可用问题

项目场景&#xff1a; 自己开发的文件服务项目在使用时测试反馈在下载文件时&#xff0c;文件名包含逗号时下载失败&#xff0c;无法跳转到下载链接页面。 项目使用springboot开发&#xff0c;文件的上传基于SpringMVC的表单文件上传。但是下载时由于需要下载原文件名&#xf…

【IC设计】基于Verilog的8层矩阵乘法设计

文章目录 项目要求基本要求截断要求低位截断高位饱和 参考结果 项目实现实现思路实现代码matrix_multiplier_16.vtb_mm_mlp.v VCS&Verdi综合前仿真dc综合VCS&Verdi综合后仿真不足之处 项目要求 基本要求 输入有9个矩阵&#xff0c;权重矩阵有8个&#xff0c;分别是We…

win11安装open-ssh server

帮助链接&#xff1a; 安装 OpenSSH | Microsoft Learn step1: 本机管理模式的power shell下查询安装状态 Get-WindowsCapability -Online | Where-Object Name -like OpenSSH* Name : OpenSSH.Client~~~~0.0.1.0 State : InstalledName : OpenSSH.Server~~~~0.0.1.0 Stat…

Kafka生产者与消费者api示例

生产者api示例 一个正常的生产逻辑需要具备以下几个步骤 配置生产者参数及创建相应的生产者实例 构建待发送的消息 发送消息 关闭生产者实例 采用默认分区方式将消息散列的发送到各个分区当中 package com.doitedu;import org.apache.kafka.clients.producer.KafkaProduce…

【人工智能】— 线性分类器、感知机、损失函数的选取、最小二乘法分类、模型复杂性和过度拟合、规范化

【人工智能】— 感知机、线性分类器、感知机、感知机、最小二乘法分类、模型复杂性和过度拟合、规范化 Linear predictions 线性预测分类线性分类器感知机感知机学习策略损失函数的选取距离的计算 最小二乘法分类求解最小二乘分类矩阵解法一般线性分类模型复杂性和过度拟合训练…

重估端到端原则

评价技术迭代的旧的定势眼光来自于该技术诞生时。 1970/80/90 年代&#xff0c;相比传输带宽技术&#xff0c;处理器更强。网络协议倾向于字段多&#xff0c;字段小且紧凑&#xff0c;尽可能减少传输量&#xff0c;用 “算法技巧” 等价&#xff0c;如果 TCP 序列号 48 位&…

【iOS】消息传递和消息转发机制

消息传递机制 在OC语言中&#xff0c;调用对象的方法被叫做消息传递。消息有名称和选择子(selector)&#xff0c;可以接受参数&#xff0c;还可能有返回值。 在Objective-C中&#xff0c;如果向某对象传递消息&#xff0c;那就会使用动态绑定机制来决定需要调用的方法。在底层…

C++进阶 —— 范围for(C++11新特性)

目录 一&#xff0c;范围for介绍 二&#xff0c;范围for注意事项 一&#xff0c;范围for介绍 范围for&#xff08;range-based for loop&#xff09;是C11新引入的特性&#xff0c;可遍历各种序列结构的容器&#xff08;如数组、vector、list等&#xff09;&#xff1b;每次循…

【QT】Qt ApplicationManager Compositor源码分析

Qt ApplicationManager的Compositor功能分析 根据Qt ApplicationManager官网介绍&#xff0c;它基于Wayland协议实现了Compositor功能。下述为官网介绍。实际上&#xff0c;QtApplicationManager是使用了QtWayland模块来实现Compositor的。Wayland是一套旨在替代XWindow的 Com…

微机实验:第5章——存储器设计

存储器设计 将两片6116所有的存储单元都写入11H。 提示&#xff1a;6116的存储容量为2K*8b&#xff0c;片内地址为0000H-07FFH,两片一起构成F8000H-F8FFFH的内存空间。 仿真调试时可以看到&#xff1a;每片从0000H-07FFH的每个存储单元均显示11H。 CODE SEGMENTASSUME CS:C…