leetcode hot100普通动态规划/基础DP

news2025/3/16 7:49:04

1️⃣1️⃣ 普通动态规划(基础 DP)

70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

题解:

  • 动态规划Dynamic Programming ,在观察动态中找到如何规划解题的步骤

  • 本题中, n=1,sov=1,n=2,sov=2;n=3时, 3=1+2=2+1,也就是说台阶为3时, 在第一阶就还需要爬两节,在第二阶就还需要爬一节, n=4=3+1=2+2,以此类推

  • dp[i]=dp[i-1]+dp[i-2]即为解

  • public int climbStairs(int n){
        if(n==1) return 1;
        if(n==2) return 2;
        int[] dp = new int[n+1];
        dp[1]=1;
        dp[2]=2;
        for(int i=3;i<=n;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];
    }
    

118. 杨辉三角

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。

题解:

  • 每一行第i个数由上一行的i.val+(i-1).val组成,即是题解

  • public List<List<Integer>> generate(int numRows) {
            // if(numRows==1){return new ArrayList<>(List.of(1));}
            // if(numRows==2){return new ArrayList<>(List.of(1,1));}
            List<List<Integer>> res = new ArrayList<List<Integer>>();
            List<Integer> org = new ArrayList<>(List.of(1));
            res.add(org);
            if(numRows==1){
                return res;
            }
            for(int i=2;i<=numRows;i++){
                List<Integer> temp = new ArrayList<>();
                temp.add(1);
                for(int j=1;j<org.size();j++){
                    temp.add(org.get(j)+org.get(j-1));
                }
                temp.add(1);
                org=temp;
                res.add(org);
            }
            return res;
        }
    

198. 打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

题解:

  • 动态规划就是计算共i间房屋, 到了第i间房屋能够偷到的最大金额,用dp[]数组标识

  • dp[i] = Math.max(dp[i-2]+nums[i],dp[i-1])

  • class Solution {
        public int rob(int[] nums) {
          if(nums==null||nums.length==0){
            return 0;
          }
          int n = nums.length;
          if(n==1){
            return nums[0];
          }
          int[] dp = new int[n];
          dp[0]=nums[0];
          dp[1]=Math.max(nums[0],nums[1]);
          for(int i=2;i<n;i++){
            dp[i]=Math.max(dp[i-2]+nums[i],dp[i-1]);
          }
          return dp[n-1];
        }
    }
    

279. 完全平方数

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

题解:

  • 对于一个数nums,它的最小完全平方数dp[nums],

  • 从1~num这个过程, 我们可以逐渐建立一个dp[i]为num=i时的最小完全平方数, 建立过程如下:

    • 1~i存在一个j, 这个j使得dp[i-j*j]是最小的解, 那么dp[i]=dp[i-j*j]+1
    • 那么在j*j<=i的循环内, 采用min记录找到该j即可
  • class Solution {
        public int numSquares(int n) {
            int[] dp=new int[n+1];
            for(int i=1;i<=n;i++){
                int minn=Integer.MAX_VALUE;
                for(int j=1;j*j<=i;j++){
                    minn=Math.min(minn,dp[i-j*j]);
                }
                dp[i]=minn+1;
            }
            return dp[n];
        }
    }
    

322. 零钱兑换

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。你可以认为每种硬币的数量是无限的。

题解:

  • 跟上题是一样的思路, 动态维持从1~amount的最小零钱数

  • class Solution {
        public int coinChange(int[] coins, int amount) {
            int n=coins.length;
            int[] dp = new int[amount+1];
            for(int i=1;i<=amount;i++){
                int minn=Integer.MAX_VALUE;
                int find=0;
                for(int j=n-1;j>=0;j--){
                    if(coins[j]<=i&&dp[i-coins[j]]!=-1){
                        find=1;
                        minn=Math.min(minn,dp[i-coins[j]]);
                    }
                }
                if(find==1){
                        dp[i]=minn+1;
                    }else{
                        dp[i]=-1;
                    }
            }
            return dp[amount];
        }
    }
    

139. 单词拆分

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

题解:

  • 为了更好的判断s中是否存在字典中的单词, 将字典转化为集合Set, 基于哈希表实现的set能够直接判断是否存在/contains

  • 存一个布尔数组, 判断在s的第i个位置, 该子串是否合法

  • 从s头遍历到尾部, 遍历到i时, 如果0~i存在一个j使得s[0,j]在字典中且s[j,i]在字典中, 那么说明s[0,i]在字典中,即dp[i]=true,那么此处就存在一个DP,每次步入一个新的i,判断其中是否存在j使得上述成立, 直至i=s.length()

  • class Solution {
        public boolean wordBreak(String s, List<String> wordDict) {
            Set<String> wordDictSet = new HashSet(wordDict);
            boolean[] dp = new boolean[s.length()+1];
            dp[0]=true;
            for(int i=1;i<=s.length();i++){
                for(int j=0;j<i;j++){
                    if(dp[j]&&wordDictSet.contains(s.substring(j,i))){
                        dp[i]=true;
                        break;
                    }
                }
            }
            return dp[s.length()];
        }
    }
    

300. 最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

题解:

  • 最初想到用进出栈的方式维护一个递增子序列, 但是 进出栈维护的是递增的连续子序列,而不是子序列, 给出一个例子就能明白:

    • [10,20,10,30,40],最大的递增连续子序列是3-[10,30,40],而最大递增子序列是4-[10,20,30,40]
  • 上法不通,采用动态规划: 维护一个长度为n的dp数组,dp[i]代表的是nums索引从0到i的最长递增子序列的长度, 那么就能得到:

    • dp[i] = max(dp[j])+1, 0<j<i, 前提是nums[j] < nums[i]
    • 此法从头遍历, 每个i再遍历0~ i-1 即可
    • 本方法的时间复杂度是n^2
  • 是否可以优化一下, 上法可以看出 ,每次循环遍历查找max(dp[j])存在很大浪费的, 如果能够存储当前最大长度所在的最小nums值就好了, 那么能否实现 维护一个d[]数组, 下表i为最长递增子序列的大小, 那么d[i]即为当前序列能够维持的最小num

    • 至于d[i]如果再现在更新为一个比之前小的值, 那么原本存储在该位置的值会存在哪里, 可以把d[i]看作一个桶, 越早存的数据移动到里面

    • class Solution {
          public int lengthOfLIS(int[] nums) {
              int n = nums.length;
              if(n==0||n==1) return n;
              int[] d = new int[n+1];
              int len = 1;
              d[len] = nums[0];
              for(int i=1;i<n;i++){
                  if(nums[i]>d[len]){
                      d[++len] = nums[i];
                  }else{
                      int l=1,r=len,pos=0;
                      while(l<=r){
                          int mid = (l+r) >>1;
                          if(d[mid]<nums[i]){
                              pos = mid;
                              l=mid+1;
                          }else{
                              r=mid-1;
                          }
                      }
                      d[pos+1] = nums[i];
                  }
              }
              return len;
          }
      }//pos设置为0且最后是d[pos+1]=nums[i]的原因在于二分查找中, pos+1能够定位到最后一个小于nums[i]的d[i], pos+1就能定位到第一个大于nums[i]的d[i]
      
  • 与本题有关的是一道阿里的笔试题:
    在这里插入图片描述

    • 也是需要维护一个LIS/最长连续子序列
    • 读取数据后根据x属性升序排序, 然后对于y值维护一个最长连续子序列即可

152. 乘积最大子数组

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续 子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。测试用例的答案是一个 32-位 整数。

题解:

  • 索引i的最大值不再能够依赖索引i-1的最大值来判断, 即,当前位置的最优解未必是由前一个位置的最优解转移得到的

  • 关键的就是负数会使当前最大值变为最小值, 如果后面再次出现负数又会使当前最小值变为最大值, 关键在于维护当前的最小值和最大值

  • 如果出现负数, 那么前一位的最大值会变成最小值, 前一位的最小值会变成最大值, 那么当前的最大值=Math.max(前面的最大值*当前值,当前值),当前的最小值=Math.min(前面的最小值*当前值, 当前值)

  • class Solution {
        public int maxProduct(int[] nums) {
            int n = nums.length;
            int res = nums[0];
            int[] max = new int[n];
            int[] min = new int[n];
            max[0] = min[0] = nums[0];
            for(int i=1;i< n;i++){
                if(nums[i]<=0){
                    int[]  temp = max;
                    max = min;
                    min = temp;
                }
                max[i] = Math.max(max[i-1]*nums[i],nums[i]);
                min[i] = Math.min(min[i-1]*nums[i],nums[i]);
                res = Math.max(max[i],res);
            }
            return res;
        }
    }
    

416. 分割等和子集

最无法理解的一题…谁爱做谁做去…看都看不懂…

32. 最长有效括号

给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

题解:

  • 对于这种求最值的题目, 可能需要用到的就是动态规划了, 研究最优策略, 根据子问题的可递归性得到转移方程

  • 本题的子问题就是, 对于一个’)‘来说, 找出与它配对的’(’

  • 维护一个dp数组, 对于i索引来说, dp[i]表述以nums[i]为结尾字符的最长有效字符长度

  • 如果s[i] = ‘(’ 那么无法与其之前的元素组成有效的括号对, 所以dp[i]=0;如果s[i] = ‘)’ 那么分情况考虑

    • s[i-1]=‘(’ : 则该二者组成有效括号, 有效括号长度新增2,即dp[i] = dp[i-2]+2 --此处还需判断i-2是否有效即是否在边界值内
    • s[i-1]=‘)’: 则该二者的左括号必定在前面, 需要先找到s[i-1]的左括号在哪, dp[i-1]的长度就是s[i-1]左右括号匹配的长度, 那么与s[i]匹配的左括号的位置就是i-dp[i-1]-1; 那么dp[i] = dp[i-1]+2+dp[i-dp[i-1]-1-1](就是还得加上s[i]匹配的左括号的前面部分的有效括号长度,不排除为0的可能)
  • class Solution {
        public int longestValidParentheses(String s) {
            int n = s.length();
            int maxAns = 0;
            int[] dp = new int[n];
            for(int i = 1;i<n;i++){
                if(s.charAt(i)==')'){
                    if(s.charAt(i-1)=='('){
                        dp[i] = (i>=2 ? dp[i-2] : 0) +2;
                    }else if(i-dp[i-1]> 0&&s.charAt(i-1-dp[i-1])=='('){
                        dp[i] = dp[i-1]+((i-dp[i-1]) >= 2? dp[i-dp[i-1]-2] : 0) +2;
                    }
                    maxAns = Math.max(maxAns,dp[i]);
                }
            }
            return maxAns;
        }
    }
    

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

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

相关文章

基于Python的天气预报数据可视化分析系统-Flask+html

开发语言&#xff1a;Python框架&#xff1a;flaskPython版本&#xff1a;python3.8数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 系统登录 可视化界面 天气地图 天气分析 历史天气 用户管理 摘要 本文介绍了基于大数据…

【鸿蒙开发】Hi3861学习笔记-Visual Studio Code安装(New)

00. 目录 文章目录 00. 目录01. Visual Studio Code概述02. Visual Studio Code下载03. Visual Studio Code安装04. Visual Studio Code插件05. 附录 01. Visual Studio Code概述 vscode是一种简化且高效的代码编辑器&#xff0c;同时支持诸如调试&#xff0c;任务执行和版本管…

Redis基本命令手册——五大类型

目录 一&#xff1a;基本操作 二&#xff1a;字符串&#xff08;String&#xff09; 三&#xff1a;哈希&#xff08;Hash) 四&#xff1a;列表&#xff08;List&#xff09; 五&#xff1a;集合&#xff08;Set&#xff09; 六&#xff1a;有序集合&#xff08;Zset&…

历年华中科技大学计算机考研复试上机真题

历年华中科技大学计算机考研复试上机真题 2022华中科技大学计算机考研复试上机真题 2021华中科技大学计算机考研复试上机真题 2019华中科技大学计算机考研复试上机真题 在线评测&#xff1a;https://pgcode.cn 八进制 题目描述 输入一个整数&#xff0c;将其转换成八进制数…

Python----数据分析(Pandas二:一维数组Series,Series的创建,Series的属性,Series中元素的索引与访问)

一、一维数组Series Series&#xff1a;一维数组,与Numpy中的一维array类似。它是一种类似于一维数组的对象&#xff0c;是由一组数据(各种 NumPy 数据类型)以及一组与之相关的数据标签(即索引)组成。 仅由一组数据也可产生简单的 Series 对象&#xff0c;用值列表生成 Series …

java数据结构(复杂度)

一.时间复杂度和空间复杂度 1.时间复杂度 衡量一个程序好坏的标准&#xff0c;除了能处理各种异常&#xff0c;还有就是时间效率&#xff0c;当然&#xff0c;对于一些配置好的电脑数据处理起来就是比配置低的高&#xff0c;但从后期发展来看&#xff0c;当数据量足够庞大时&…

windows协议不再续签,华为再无windows可用,将于四月发布鸿蒙PC

大家好&#xff0c;我是国货系创始人张云泽&#xff0c;最近不少小伙伴在后台问&#xff1a;“听说Windows协议要到期了&#xff1f;我的电脑会不会变砖&#xff1f;”还有人说&#xff1a;“华为笔记本以后用不了Windows了&#xff1f;鸿蒙系统能用吗&#xff1f;”今天咱们就…

HTML+CSS基础(了解水平)

html 的介绍 学习目标 能够知道html的作用 1. html的定义 2. html的定义 HTML 的全称为&#xff1a;HyperText Mark-up Language, 指的是超文本标记语言。 标记&#xff1a;就是标签, <标签名称> </标签名称>, 比如: <html></html>、<h1><…

[设计模式]1_设计模式概览

摘要&#xff1a;设计模式原则、设计模式的划分与简要概括&#xff0c;怎么使用重构获得设计模式并改善代码的坏味道。 本篇作概览与检索用&#xff0c;后续结合源码进行具体模式深入学习。 目录 1、设计模式原理 核心原则&#xff08;语言无关&#xff09; 本质原理图 原…

Elasticsearch集群与日志系统实战部署指南

一、环境规划与初始化配置 1. 服务器资源分配 IP地址部署服务主机名172.25.23.7ES Kafka Zookeeper Kibananode1172.25.23.8ES Kafka Zookeeper Filebeatnode2172.25.23.9Kafka Zookeeper Apache Logstashnode3 系统要求&#xff1a; 配置&#xff1a;4核CPU / 4G…

SFT数据处理部分的思考

SFT数据及处理的业内共识 1&#xff0e;prompt的质量和多样性远重要于数据量级&#xff0c;微调一个 30 b 量级的base model只需要 10 w 量级的数据即可 参考&#xff1a;《LIMA&#xff1a;Less Is More for Alignment》 2&#xff0e;合成数据很重要&#xff01;一般需要通过…

netsh实现TCP端口转发

服务器&#xff1a;192.168.31.9 端口&#xff1a;56000 客户端&#xff1a;192.168.31.2 端口&#xff1a;5600 客户端&#xff08;本地端口5600&#xff09;通过TCP连接服务器的56000端口 PC&#xff1a;192.168.31.5&#xff0c;PC实现客户端和服务器之间56000端口转发 1. …

leetcode 75.颜色分类(荷兰国旗问题)

题目描述 题目分析 本题是经典的「荷兰国旗问题」&#xff0c;由计算机科学家 Edsger W. Dijkstra 首先提出。 要想单独解决这道题本身还是很简单的&#xff0c;统计0、1、2的数量然后按顺序赋值&#xff0c;或者手写一个冒泡排序&#xff0c;whatever。 但是在这一题中我们主…

在windows上通过idea搭建doris fe的开发环境(快速成功版)

一、前置环境准备 1. 准备Linux环境&#xff0c;我起的虚机&#xff0c;使用CentOS8&#xff0c;4核、12G&#xff0c;磁盘50G 1.1.备份yum源 # 系统下载连接&#xff1a;magnet:?xturn:btih:9DB46A612D04763AA7DB02A0FF63EDE2EA555867&dnCentOS-8.1.1911-x86_64-dvd1.…

MyBatis源码分析の配置文件解析

文章目录 前言一、SqlSessionFactoryBuilder1.1、XMLConfigBuilder1.2、parse 二、mappers标签的解析2.1、cacheElement2.1.1、缓存策略 2.2、buildStatementFromContext2.2.1、sql的解析 前言 本篇主要介绍MyBatis源码中的配置文件解析部分。MyBatis是对于传统JDBC的封装&…

python爬虫笔记(一)

文章目录 html基础标签和下划线无序列表和有序列表表格加边框 html的属性a标签&#xff08;网站&#xff09;target属性换行线和水平分割线 图片设置宽高width&#xff0c;height html区块——块元素与行内元素块元素与行内元素块元素举例行内元素举例 表单from标签type属性pla…

DC-6靶机详解

一、主机发现 arp-scan -l靶机ip为192.168.55.159 二、端口扫描、目录枚举、指纹识别、 2.1端口扫描 nmap 192.168.55.159发现没有开放特殊端口 看来信息收集的重点要放在网页中了 2.2目录枚举 dirb http://192.168.55.1592.3指纹识别 nmap 192.168.55.159 -sV -sC -O …

STM32-SPI通信外设

目录 一&#xff1a;SPI外设简介 SPI框图​编辑 SPI逻辑 ​编辑 主模式全双工连续传输 ​编辑 非连续传输 二&#xff1a;硬件SPI读写W25Q64 1.接线&#xff1a; 2. 代码 SPI外设的初始化 生成时序 一&#xff1a;SPI外设简介 STM32内部集成了硬件SPI收发电路&#…

远程控制中的云电脑是什么意思?1分钟学会用

很多常用我们ToDesk远程控制的朋友们或许会注意到无论是在PC端还是移动端中都出现有【云电脑】【来云电脑爽玩-新用户免费1小时】这些词句等信息。那么这究竟是代表什么意思呐&#xff1f;云电脑是什么又怎么用呐&#xff1f;为什么要增加云电脑&#xff1f;以下小编就为大家科…

网络爬虫【简介】

我叫补三补四&#xff0c;很高兴见到大家&#xff0c;欢迎一起学习交流和进步 今天来讲一讲视图 一、网络爬虫的定义 网络爬虫&#xff08;Web Crawler&#xff09;&#xff0c;又称为网络蜘蛛、网络机器人等&#xff0c;是一种按照一定规则自动抓取互联网信息的程序或脚本。它…