动态规划/贪心算法

news2025/3/5 20:52:30

一、动态规划

动态规划 是一种用于解决优化问题的算法设计技术,尤其适用于具有重叠子问题和最优子结构性质的问题。它通过将复杂问题分解为更简单的子问题,并保存这些子问题的解以避免重复计算,从而提高效率。

动态规划的核心思想

  1. 最优子结构(Optimal Substructure)

    • 一个问题的最优解可以通过其子问题的最优解来构造。
    • 比如在最短路径问题中,从起点到终点的最短路径可以由起点到某个中间点的最短路径和该中间点到终点的最短路径组合而成。
  2. 重叠子问题(Overlapping Subproblems)

    • 在递归求解过程中,相同的子问题会被多次求解。
    • 动态规划通过存储子问题的解来避免重复计算,通常使用数组或哈希表等数据结构来存储这些解。

1.算法原理

1)状态表示

dp表(一维数组  填满该表其中某一个值就是结果 数组中某个数据值的意义就是状态表示)

通过题目要求 经验  分析问题发现重复子问题 来创建dp表

2)状态转移方程

dp[i]等于什么?

3)初始化

根据状态转移方程填表,保证填表的时候不越界

4)填表顺序

为了填写当前状态的时候,所需要的状态已经计算过了

5)返回值

题目要求+状态表示

2.例题

泰波那契序列 Tn 定义如下: 

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

示例 1:输入:n = 4 输出:4    解释: T_3 = 0 + 1 + 1 = 2 T_4 = 1 + 1 + 2 = 4

状态表示:dp[i]第i个泰波那契数的值

状态转移方程:dp[i]=dp[i-1]+dp[i-2]+dp[i-3];

初始化:dp[0]=0;dp[1]=1;dp[2]=1

填表顺序:从左向右

返回值:dp[n]

JAVA代码

class Solution {
    public int tribonacci(int n) {
if(n==0) return 0;
if(n==1||n==2) return 1;
int[] dp=new int[n+1];
dp[0]=0;dp[1]=1;dp[2]=1;
for(int i=3;i<=n;i++){
    dp[i]=dp[i-1]+dp[i-2]+dp[i-3];
}
return dp[n];
    }
}

3.空间优化

求解某个状态时仅需要其的前几个状态

一定要确定好赋序

int tribonacci(int n){
//空间优化 滚动数组
if(n==0) return 0;
if(n==1||n==2) return 1;
int a=0;int b=1,c=1;int d=0;
for(int i=3;i<=n;i++){
    d=a+b+c;
    a=b;
    b=c;
    c=d;

}
return d;
}

 二、贪心算法

1.算法原理:

局部最优->全局最优

把解决问题的过程分为若干步,解决每一步的时候都选择当前看起来最优的解

希望得到全局最优解

但贪心算法并不总是保证全局最优解

2.例题

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

示例 1:

[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

在数组中挑出两个数,使其差值最大

1)暴力解法(两层for循环) 超出时间限制时间复杂度O(n^2)

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

class Solution {
    public int maxProfit(int[] prices) {
        int ret = 0;
        if (prices == null || prices.length < 2) {
            return 0;
        }
        for (int i = 0; i < prices.length - 1; i++) {
            for (int j = i+1; j < prices.length; j++) {
                ret = Math.max(ret, prices[j] - prices[i]);
            }
        }
        return ret;
    }


        public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Solution solution=new Solution();
        List<Integer> pricesList = new ArrayList<>();
        while (sc.hasNextInt()) {
            pricesList.add(sc.nextInt());
        }
        int[] prices = new int[pricesList.size()];
        for (int i = 0; i < pricesList.size(); i++) {
            prices[i] = pricesList.get(i);
        }
        int ret=solution.maxProfit(prices);
        System.out.println(ret);
        sc.close();
    }
}//在输入结束后输入一个非数字字符(如字母 'q'),这样 hasNextInt() 会返回 false,从而结束循环,或 Ctrl + Z(Windows)来发送 EOF 信号。

2)贪心

分为两段,prevmin表示前一段中最小值(买入),prices[i]卖出去的价钱

class Solution {
    public int maxProfit(int[] prices) {
        int ret=0;
        for(int i=0,prevmin=Integer.MAX_VALUE;i<prices.length;i++){
            ret=Math.max(ret,prices[i]-prevmin);
            prevmin=Math.min(prevmin,prices[i]);
        }
        return ret;
    }
}

三、 (双指针算法)

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

数组划分

利用数组下标充当指针 

两个指针的作用:

cur:从左往右扫描,遍历数组

dest:已处理的区间内,非0元素的最后一个位置

三个区间:

[0,dest]   [dest+1,cur-1]  [cur,n-1]

非0         0元素                 待处理的区间

解法:

初始dest=-1 cur=0

遇到0元素,cur++;

遇到非0元素 swap(dest+1,cur)交换位置 dest++ cur++

class Solution {
    public void moveZeroes(int[] nums) {
int dest=-1;
int cur=0;
int k=0;
int n=nums.length;
while(cur<n){
if(nums[cur]==0)
cur++;
else
{dest++;
k=nums[dest];
nums[dest]=nums[cur];
nums[cur]=k;
cur++;
}

}

}
}

 

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

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

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

输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3。
最大总利润为 4 + 3 = 7 。

利用数组下标充当指针(i,j)

class Solution {
    public int maxProfit(int[] prices) {
        //双指针算法
        int ret=0;
        int i=0,j=0;
        for(i=0;i<prices.length;i++){
            j=i;
            while(j+1<prices.length && prices[j+1]-prices[j]>0){
                j++;
            }
            ret+=prices[j]-prices[i];
            i=j;
        }
        return ret;
           }
}

四、递归

1.什么是递归

函数自己调用自己(主问题->相同的子问题)

出口(一个问题不能在分割了)           

1.算法思想

函数头 函数体 递归出口

把递归的函数当成一个黑盒,不在意递归的细节

深度优先遍历(后序遍历)

2.例题

计算布尔二叉树的值

给你一棵 完整二叉树 的根,这棵树有以下特征:

  • 叶子节点 要么值为 0 要么值为 1 ,其中 0 表示 False ,1 表示 True 。
  • 非叶子节点 要么值为 2 要么值为 3 ,其中 2 表示逻辑或 OR ,3 表示逻辑与 AND 。

计算 一个节点的值方式如下:

  • 如果节点是个叶子节点,那么节点的  为它本身,即 True 或者 False 。
  • 否则,计算 两个孩子的节点值,然后将该节点的运算符对两个孩子值进行 运算 。

返回根节点 root 的布尔运算值。

完整二叉树 是每个节点有 0 个或者 2 个孩子的二叉树。

叶子节点 是没有孩子的节点。

class Solution {
    public boolean evaluateTree(TreeNode root) {
        if(root.left==null) return root.val==0 ? false: true;
        boolean left=evaluateTree(root.left);
        boolean right=evaluateTree(root.right);
        return root.val==2 ?left | right : left & right;
    }
}

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

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

相关文章

python全栈-Linux基础

python全栈-Linux基础 文章目录 Linux安装/配置网络配置配置Linux远程登录配置虚拟机内部ip配置真机的ip安装XShell和Xftp目录结构用户和用户组用户管理添加用户useradd查看用户id修改用户usermod (选项)(参数)用户密码设置passed (选项)(参数)删除用户userdel [选项] 用户名 用…

基于https虚拟主机配置

一、https介绍 http 明文&#xff0c;80/tcp https 密文&#xff0c;443/tcp 二、安全性保障 1、数据安全性 数据加密 2、数据完整性 3、验证身份的真实性、有效性 三、数据安全性 手段&#xff1a;加密 发送方加密数据&#xff0c;接收方解密数据 对称加密算法 加密、解密数据…

Kmeans算法来实现RFM指标计算步骤

K-Means&#xff08;K均值&#xff09;是一种经典的无监督聚类算法&#xff0c;主要用于将数据集划分为 KKK 个不同的簇&#xff08;Cluster&#xff09;。 它基于最小化簇内样本的平方误差&#xff0c;即最小化数据点与簇中心的距离之和。 1. K-Means 算法原理 (1) 主要步骤 …

Vue2-3 优雅的在子组件修改父组件传递过来的v-model

在子组件修改父组件传递过来的v-model&#xff0c;这样会破坏单向数据流&#xff0c;造成屎山代码&#xff0c;为了避免这个问题&#xff0c;需要给一个中间层来相对舒服的使用v-model。方法就是用computed去拦截v-model,然后在computed 里面去触发 emit 事件来修改父组件传来的…

threejs:用着色器给模型添加光带扫描效果

第一步&#xff1a;给模型添加光带 首先创建一个立方体&#xff0c;不进行任何缩放平移操作&#xff0c;也不要set position。 基础代码如下&#xff1a; 在顶点着色器代码里varying vec3 vPosition;vPosition position;获得threejs自动计算的顶点坐标插值&#xff08;也就…

1.从0搭建前端Vue项目工程

我们通过vue官方提供的脚手架Vue-cli来快速生成一个Vue的项目模板。 **注意&#xff1a;**需要先安装NodeJS&#xff0c;然后才能安装Vue-cli。 环境准备好了&#xff0c;接下来我们需要通过Vue-cli创建一个vue项目&#xff0c;然后再学习一下vue项目的目录结构。Vue-cli提供了…

开放鸿蒙OpenHarmony 5.0.0 Release 兼容性测试实战经验分享

OpenHarmony 5.0版本的发布时间是2024年12月20日至21日。这个版本带来了许多新特性和改进。现在5.0出了两个release 版本&#xff0c;分别是5.0.0和5.0.1。 就在5.0版本发布不到2周的时间内&#xff0c;2025年01月01日起&#xff0c;不支持新产品基于老分支&#xff08;OpenHar…

Chromium_src源码

Chromium_src源码 码云上有一个OpenHarmony-TPC/chromium_src项目&#xff0c;目前已经停止维护了&#xff0c;迁移到GitCode上了&#xff0c;源代码项目地址为&#xff1a;openharmony-tpc/chromium_chrome 特此记录一下老的项目的相关软件架构 Chromium 简介 软件架构 软…

深度学习的正则化深入探讨

文章目录 一、说明二、学习目标三、什么是机器学习中的正则化四、了解过拟合和欠拟合五、代价函数的意义六、什么是偏差和方差&#xff1f;七、机器学习中的正则化&#xff1f; 一、说明 在训练机器学习模型时&#xff0c;模型很容易过拟合或欠拟合。为了避免这种情况&#xf…

《OpenCV》——dlib(人脸应用实例)

文章目录 dlib库dlib库——人脸应用实例——表情识别dlib库——人脸应用实例——疲劳检测 dlib库 dlib库的基础用法介绍可以参考这篇文章&#xff1a;https://blog.csdn.net/lou0720/article/details/145968062?spm1011.2415.3001.5331&#xff0c;故此这篇文章只介绍dlib的人…

tauri2+typescript+vue+vite+leaflet等的简单联合使用(一)

项目目标 主要的目的是学习tauri。 流程 1、搭建项目 2、简单的在项目使用leaflet 3、打包 准备项目 环境准备 废话不多说&#xff0c;直接开始 需要有准备能运行Rust的环境和Node&#xff0c;对于Rust可以参考下面这位大佬的文章&#xff0c;Node不必细说。 Rust 和…

本地部署阿里万象2.1文生视频模型(Wan2.1-T2V)完全指南

在生成式AI技术爆发式发展的今天,阿里云开源的万象2.1(Wan2.1)视频生成模型,为创作者提供了从文字/图像到高清视频的一站式解决方案。本文针对消费级显卡用户,以RTX 4060 Ti 16G为例,详解本地部署全流程与性能调优方案,涵盖环境配置、多模型选择策略、显存优化技巧及实战…

【Vue CLI脚手架开发】——3.组件交互props配置

文章目录 前言一、props数据接收方式二、代码实现1. 父组件2.子组件 三、分析 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要&#xff0c;很多人都开启了学习机器学习…

FPGA之USB通信实战:基于FX2芯片的Slave FIFO回环测试详解

FPGA之Usb数据传输 Usb 通信 你也许会有疑问&#xff0c;明明有这么多通信方式和数据传输&#xff08;SPI、I2C、UART、以太网&#xff09;为什么偏偏使用USB呢? 原因有很多&#xff0c;如下&#xff1a; 1. 高速数据传输能力 高带宽&#xff1a;USB接口提供了较高的数据传…

【Office-Word】如何自动生成中英文目录

1.目录介绍 Word这个自动生成目录非常强大&#xff0c;涉及的功能很琐碎&#xff0c;想要完美的生成目录不仅仅是只会目录这么简单&#xff0c;前后涉及到的大纲级别、目标样式和域代码等操作是比较头疼的。 下面就一步一步开始介绍 2.多级标题级别编号设置 目录想要设置好…

CentOS 7 安装Nginx-1.26.3

无论安装啥工具、首先认准了就是官网。Nginx Nginx官网下载安装包 Windows下载&#xff1a; http://nginx.org/download/nginx-1.26.3.zipLinxu下载 wget http://nginx.org/download/nginx-1.26.3.tar.gzLinux安装Nginx-1.26.3 安装之前先安装Nginx依赖包、自行选择 yum -y i…

家政预约小程序用例图分析

在和客户进行需求沟通的时候&#xff0c;除了使用常规的问答的形式&#xff0c;我还使用图形化工具更深入的沟通。比如借助UML的用例图来开展系统分析&#xff0c;并且按照角色详细拆解了家政预约小程序的各个用例。在分析阶段思考的越多&#xff0c;沟通的越多&#xff0c;在系…

112页精品PPT | DeepSeek行业应用实践报告

这份文件是一份关于DeepSeek行业应用实践的报告&#xff0c;以PPT形式呈现&#xff0c;共112页&#xff0c;详细介绍了DeepSeek及其核心产品DeepSeek-R1的技术特点、市场表现、应用路径以及在多领域的实践案例。报告展示了DeepSeek在市场上的快速崛起&#xff0c;包括其日活用户…

计算机毕业设计SpringBoot+Vue.js航空机票预定系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

C语言学习笔记-初阶(27)操作符详解1:位操作

1. 操作符的分类 上述的操作符&#xff0c;我们已经学过算术操作符、赋值操作符、逻辑操作符、条件操作符和部分的单目操作符&#xff0c;今天继续介绍⼀部分&#xff0c;操作符中有一些操作符和二进制有关系&#xff0c;我们先铺垫一下二进制的和进制转换的知识。 2. 二进制、…