Python数据结构与算法——算法(贪心算法、动态规划

news2024/11/18 2:38:19

贪心算法

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

贪心算法并不保证会得到最优解,但是在某些问题上贪心算法的解就是最优解。要会判断一个问题能否用贪心算法来计算。

例一:找零问题

问题:假设商店老板需要找零n元钱,钱币的面额有:100元、50元、20元、5元、1元,如何找零使得所需的钱币数量最少?

思路:为了找的钱币最少,从最大面额找,找不开就用比它小的找...

t = [100, 50, 20, 5, 1]

def change(t, n):
    m = [0 for _ in range(len(t))]
    for i, money in enumerate(t):
        m[i] = n // money
        n = n % money
    return m, n

print(change(t, 376))

 例二:背包问题

问题:一个小偷在某个商店发现有n个商品,第i个商品价值vi元,重wi千克。他希望拿走的价值尽量高,但他的背包最多只能容纳W千克的东西。他应该拿走哪些商品?

  • 0-1背包:对于一个商品,小偷要么把它完整拿走,要么留下。不能只拿走一部分,或把一个商品拿走多次。(商品为金条)
  • 分数背包:对于一个商品,小偷可以拿走其中任意一部分。(商品为金砂)

分数背包使用贪心算法没有问题,但是0-1背包不可以!

分数背包

goods = [(60, 10), (120, 30), (100, 20)]  # 每个商品元组表示(价格, 重量)
goods.sort(key = lambda x:x[0]/x[1], reverse = True)  # 按照单价排序

def fractional_backpack(goods, w):    
    m = [0 for _ in range(len(goods))]
    total_v = 0
    for i, (price, weight) in enumerate(goods):
        if w >= weight:
            m[i] = 1
            w -= weight
            total_v += price
        else:
            m[i] = w/weight
            total_v += m[i] * price
            w = 0
            break
    return m, total_v


print(fractional_backpack(goods, 50))

例三:拼接最大数字问题 、

问题:有n个非负整数,将其按照字符串拼接的方式拼接为一个整数,如何拼接可以使得到的整数最大?

  • 例:32、94、128、1286、6、71可以拼接的最大整数为:94716321286128
from functools import cmp_to_key

li = [32, 94, 128, 1286, 6, 71]

def xy_cmp(x, y):
    if x+y > y+x:
        return -1
    elif x+y < y+x:
        return 1
    else:
        return 0

def number_join(li):
    li = list(map(str, li))
    li.sort(key=cmp_to_key(xy_cmp))
    return "".join(li)

print(number_join(li))

例四:活动选择问题 

问题:假设有n个活动,这些活动要占用同一片场地,而场地在某时刻只能供一个活动使用。

每个活动都有一个开始时间si和结束时间fi(题目中时间以整数表示),表示活动在[si, fi)区间占用场地。

问:安排那些活动能够使该场地举办的活动个数最多?

i1234567891011
si130535688212
fi4567991011121416

思路:最先结束的活动一定是最优解的一部分。

activities = [(1, 4), (3, 5), (0, 6), (5, 7), (3, 9), (5, 9), (6, 10), (8, 11), (8, 12), (2, 14), (12, 16)]

# 保证活动是按照结束时间排好序的
activities.sort(key=lambda x:x[1])

def activity_selection(a):
    res = [a[0]]
    for i in range(1, len(a)):
        if a[i][0] >= res[-1][1]:  # 当前活动的开始时间小于等于最后一个入选活动的结束时间
            res.append(a[i])
    return res

print(activity_selection(activities))

动态规划

介绍:是一种解决复杂问题的数学方法,通常用于优化问题。动态规划将问题分解为更小的子问题,通过解决这些子问题并将它们的解存储起来,最终得到原始问题的解。

思想:

  • 最优子结构(递推式)
  • 重复子问题

什么问题使用动态规划方法?

  • 最优子结构
    • 原问题的最优解中涉及多少个子问题
    • 在确定最优解使用哪些子问题时,需要考虑多少种选择
  • 重叠子问题

例一:斐波那契数列

# 子问题的重复计算
def fibnacci(n):
    if n == 1 or n == 2:
        return 1
    else:
        return fibnacci(n-1) + fibnacci(n-2)


# 无重复计算,存在列表中——动态规划(DP)
def fibnacci_no_recurision(n):
    f = [0, 1, 1]
    if n > 2:
        for i in range(n-2):
            num = f[-1] + f[-2]
            f.append(num)
    return f[-1]

print(fibnacci_no_recurision(100))

例二:钢条切割问题

思路:

  • 设长度为n的钢条切割后的最优收益值为r_{n},可以得出递推式:r_{n} = max(p_{n}, r_{1} + r_{n-1}, r_{2} + r_{n-2}, ... , r_{n-1} + r_{1})
  • 第一个参数p_{n }表示不切割
  • 其他n-1个参数分别表示另外n-1种不同切割方案,对方案i=1,2,...,n-1
    • 将钢条切割为长度为i和n-i两段
    • 方案i的收益为切割两端的最优收益之和
  • 考察所有的i,选择其中收益最大的方案

钢条切割问题满足最优子结构,比如长度为9要切为8和1,前面已经算了8的最佳情况,直接使用即可。

自顶向下递归实现

时间复杂度:2^{n}

p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 21, 23, 24, 26, 27, 27, 28, 30, 33, 36, 39, 40]

def cut_rod_recurision_1(p, n):
    if n == 0:
        return 0
    else:
        res = p[n]
        for i in range(1, n):
            res = max(res, cut_rod_recurision_1(p, i) + cut_rod_recurision_1(p, n-i))
    return res


def cut_rod_recurision_2(p, n):
    if n == 0:
        return 0
    else:
        res = 0
        for i in range(1, n+1):
            res = max(res, p[i] + cut_rod_recurision_2(p, n-i))
    return res

print(cut_rod_recurision_1(p, 15))
print(cut_rod_recurision_2(p, 15))

自底向上动态规划实现

时间复杂度:n^{2}

p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 21, 23, 24, 26, 27, 27, 28, 30, 33, 36, 39, 40]

def cut_rod_dp(p, n):
    r = [0]
    for i in range(1, n+1):
        res = 0
        for j in range(1, i+1):
            res = max(res, p[j] + r[i-j])
        r.append(res)
    return r[n]

print(cut_rod_dp(p, 9))

重构解

同时输出最优解和最优切割方案

  • 对于每个子问题,保存切割一次时左边切下的长度

def cut_rod_extend(p, n):
    r = [0]
    s = [0]
    for i in range(1, n+1):
        res_r = 0  # 记录价格的最大值
        res_s = 0  # 记录价格最大值对应方案的左边不切割部分的长度
        for j in range(1, i+1):
            if p[j] + r[i-j] > res_r:
                res_r = p[j] + r[i-j]
                res_s = j
        r.append(res_r)
        s.append(res_s)
    return r[n], s

def cut_rod_solution(p, n):
    r, s = cut_rod_extend(p, n)
    ans = []
    while n > 0:
        ans.append(s[n])
        n -= s[n]
    return ans

print(cut_rod_solution(p, 9))

例三:最长公共子序列实现

问题:一个序列的子序列是在该序列中删去若干元素后得到的序列。

        例:"ABCD"和"BDF"都是"ABCDEFG"的子序列

给定两个序列X和Y,求X和Y长度最大的公共子序列

返回最大公共子序列长度

def lcs_length(x, y):
    m = len(x)
    n = len(y)

    # 创建一个二维数组来存储子问题的解
    dp = [[0] * (n + 1) for _ in range(m + 1)]

    # 填充dp数组
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if x[i - 1] == y[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1  # i j 位置上的字符匹配时,来自与左上方
            else:
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])

    # 从dp数组中找到最长公共子序列的长度
    return dp[m][n]


# 测试
x = "abcde"
y = "ace"
print(lcs_length(x, y))

 

代码自己手动敲一遍理解更深哦!

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

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

相关文章

发誓不在黄金周旅游,可惜管不住自己,看看景区可视化,觉悟了。

2023-10-04 23:29贝格前端工场 景区可视化大屏可以起到以下几个作用&#xff1a; 数据监控和分析&#xff1a;景区可视化大屏可以实时监控景区的各项数据指标&#xff0c;如游客数量、门票销售情况、景区设备运行状态等&#xff0c;通过可视化展示&#xff0c;管理人员可以快…

C/C++基础----指针

指针的定义 在c/c中&#xff0c;有一个特殊的变量指向我们电脑中某个内存地址&#xff0c;进而可以让我们操作这段内存&#xff0c;指的就是指针类型 语法&#xff1a; int a 10; int* p &a;&符号是取出某个变量的内存地址 把这个内存地址赋值给一个变量p&#xff…

分享一个 git stash 的实际使用场景。

当我将新的变更记录提交为 git commit --amend 后&#xff0c;发现这需要修改云端上的提交记录&#xff0c;也就是 vscode 中会出现这张图 于是&#xff0c;我通过 git reset head^ 撤销掉刚刚的提交。 reset 前&#xff1a; reset 后&#xff1a; 但在撤销的同时&#xf…

华院计算参编《金融业人工智能平台技术要求》标准

随着人工智能技术的迅猛发展&#xff0c;金融机构正在从业务场景化向企业智能化演进&#xff0c;金融业对智能化的需求愈加迫切。为引导产业有序发展、规范行业自律、加快金融行业智能化转型&#xff0c;中国信通院依托中国人工智能产业发展联盟&#xff08;AIIA&#xff09;及…

机器学习 | 使用Scikit-Learn实现分层抽样

在本文中&#xff0c;我们将学习如何使用Scikit-Learn实现分层抽样。 什么是分层抽样&#xff1f; 分层抽样是一种抽样方法&#xff0c;首先将总体的单位按某种特征分为若干次级总体&#xff08;层&#xff09;&#xff0c;然后再从每一层内进行单纯随机抽样&#xff0c;组成…

第19讲:自定义类型:结构体

1.结构体类型的声明 2.结构体变量的创建和初始化 3.结构体变量的赋值 4.结构体成员访问操作符 5.结构体内存对齐 1.结构体类型的声明 1.1结构体声明 struct 结构体名称 { 结构体成员... } 举例&#xff1a;描述一个学生&#xff1a; 2结构体变量的创建和初始化 2.1匿…

Linux文本编辑器vim使用和分析—2

目录 1.对vim的简单理解&#xff1a; 2.看待vim的视角&#xff1a; 3.命令模式&#xff1a; 3.1vim被打开后默认的模式&#xff1a; 3.2命令模式切换插入模式&#xff1a; 3.3其他模式回到命令模式&#xff1a; 3.4光标定位&#xff1a; 4.插入模式(编辑模式)&#xff1…

数字乡村创新实践探索农业现代化与农村治理现代化新路径:科技赋能农村全面振兴与农民幸福生活

目录 引言 一、数字乡村与农业现代化 1、智慧农业技术的应用 2、农业产业链的数字化转型 二、数字乡村与农村治理现代化 1、农村信息化水平的提升 2、农村治理模式的创新 三、科技赋能农村全面振兴与农民幸福生活 1、提升农业生产效益与农民收入 2、促进农村产业结构…

【ArcGIS 脚本工具】在ArcPro中实现mdb转gdb

ArcGIS Pro作为主力使用很久了&#xff0c;但是ArcMap也从来没有卸载过。 要问为什么&#xff0c;就是还需要ArcMap来读写mdb数据库&#xff0c;Pro是不支持读写mdb数据库的。 我之前尝试过不借助ArcMap把mdb转成gdb&#xff0c;奈何技术太菜搞不定。 直到我看到了公众号【G…

人工智能轨道交通行业周刊-第77期(2024.4.1-4.14)

本期关键词&#xff1a;货车巡检机器人、铁路安全技防、车辆换长、阿里千问、大模型创业 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通RailMetro轨道世界…

现代电商会员管理新玩法——付费会员

现在&#xff0c;无论是线上还是线下&#xff0c;几乎都在做会员管理。会员规则五花八门&#xff0c;不仅有常见的注册会员&#xff0c;还出现了付费会员。付费会员机制&#xff0c;从成为会员的第一步就开始筛选&#xff0c;选出粘性高、要求高、复购高且有一定消费力的用户群…

缓存与数据库的数据一致性解决方案分析

在现代应用中&#xff0c;缓存技术的使用广泛且至关重要&#xff0c;主要是为了提高数据访问速度和优化系统整体性能。缓存通过在内存或更快速的存储系统中存储经常访问的数据副本&#xff0c;使得数据检索变得迅速&#xff0c;从而避免了每次请求都需要从较慢的主存储&#xf…

labview中的同步定时结构

单帧定时循环定时比较精确&#xff0c;最常用的功能还是它的定时循环功能&#xff0c;定时循环允许不连接“循环条件”端子&#xff0c;可以连接定时循环“结构名称”端子&#xff0c;通过定时结构停止函数停止循环。 例子在附件中。

MySQL workbench使用教程(逐渐补充版)

附件&#xff1a; 附1&#xff1a;MySQL下载、安装、配置之Windows 附2&#xff1a;MySQL workbench下载、安装、配置、汉化教程 一、 使用 Workbench 操作数据库 1.MySQL Workbench 初始化界面 2.连接远程 MySQL 数据库 3.创建数据库 切换至schemas标签&#xff0c;右键单…

在家如何查找下载外文文献

查找下载外文文献的数据库大部分都需要使用权限的&#xff0c;那么我们如何在家进入这些数据库查找下载文献资源呢&#xff1f;请看本文的经验分享&#xff1a; 举例1、 一位同学的文献求助&#xff1a;Performance of financial hedging and earnings management under dive…

科研学习|科研软件——如何使用SmartPLS软件进行结构方程建模

SmartPLS是一种用于结构方程建模&#xff08;SEM&#xff09;的软件&#xff0c;它可以用于定量研究&#xff0c;尤其是在商业和社会科学领域中&#xff0c;如市场研究、管理研究、心理学研究等。 一、准备数据 在使用SmartPLS之前&#xff0c;您需要准备一个符合要求的数据集。…

【自研网关系列】请求服务模块和客户端模块实现

&#x1f308;Yu-Gateway&#xff1a;&#xff1a;基于 Netty 构建的自研 API 网关&#xff0c;采用 Java 原生实现&#xff0c;整合 Nacos 作为注册配置中心。其设计目标是为微服务架构提供高性能、可扩展的统一入口和基础设施&#xff0c;承载请求路由、安全控制、流量治理等…

EasyUI Jquery 学习笔记 ——DataGrid(数据网格)与 Tree(树)详细版

1. DataGrid(数据网格)与 Tree(树) 1.1 Datagrid 数据网格 扩展自 $.fn.panel.defaults。通过 $.fn.datagrid.defaults 重写默认的 defaults。 数据网格(datagrid)以表格格式显示数据,并为选择、排序、分组和编辑数据提供了丰富的支持。数据网格(datagrid)的设计目…

前端三件套学习笔记(持更)

目录 1、HTML,CSS,JS区别 2、HTML结构 1、HTML,CSS,JS区别 结构写到 HTML 文件中&#xff0c; 表现写到 CSS 文件中&#xff0c; 行为写到 JavaScript文件中。 2、HTML结构 <!DOCTYPE html> <html><head><title>我的第一个页面</title><…

[尚硅谷flink] 检查点笔记

在Flink中&#xff0c;有一套完整的容错机制来保证故障后的恢复&#xff0c;其中最重要的就是检查点。 文章目录 11.1 检查点11.1.1 检查点的保存1&#xff09;周期性的触发保存2&#xff09;保存的时间点3&#xff09;保存的具体流程 11.1.2 从检查点恢复状态11.1.3 检查点算法…