Day43–动态规划–674. 最长连续递增序列,300. 最长递增子序列,718. 最长重复子数组

674. 最长连续递增序列

方法:动态规划

思路:

  1. dp[i]含义:到i这个位置(包含i)的连续递增子序列的长度
  2. 递推公式:if (nums[i] > nums[i - 1]) dp[i] = dp[i - 1] + 1;
  3. 初始化:每一个nums[i]的子序列都至少是1,就是自己。Arrays.fill(dp, 1); int maxLen = 1;
  4. 遍历方向:正序
// 动态规划
class Solution {public int findLengthOfLCIS(int[] nums) {int n = nums.length;// dp[i]含义:到i这个位置(包含i)的连续递增子序列的长度int[] dp = new int[n];// 初始化:每一个nums[i]的子序列都至少是1,就是自己Arrays.fill(dp, 1);int maxLen = 1;// 从1开始遍历for (int i = 1; i < n; i++) {if (nums[i] > nums[i - 1]) {dp[i] = dp[i - 1] + 1;// 刷新最大值maxLen = Math.max(maxLen, dp[i]);}}return maxLen;}
}

方法:贪心

思路:

连续递增,就不断len++;不连续了,就更新最大值。

如果最长串,刚好到末尾的话,出了循环还要更新一次最大值。

class Solution {public int findLengthOfLCIS(int[] nums) {int n = nums.length;// 题目说n>1。所以至少有一个nums[i]。每个nums[i]的长度都是1int len = 1;int maxLen = 1;// 从1开始遍历(如果n==1的话,不进这个循环,答案也是对的)for (int i = 1; i < n; i++) {if (nums[i] > nums[i - 1]) {// 连续递增len++;} else {// 不连续了。刷新最大值maxLen = Math.max(maxLen, len);// 每个nums[i]的长度都是1len = 1;}}// 如果最长串,刚好到末尾的话。maxLen还没取到,所以出了循环还要再取一次return Math.max(maxLen, len);}
}

思路:

另一种写法

class Solution {public int findLengthOfLCIS(int[] nums) {int n = nums.length;// 题目说n>1。所以至少有一个nums[i]。每个nums[i]的长度都是1int len = 1;int maxLen = 1;// 从1开始遍历(如果n==1的话,不进这个循环,答案也是对的)for (int i = 1; i < n; i++) {if (nums[i] > nums[i - 1]) {// 连续递增len++;} else {// 重新开始,每个nums[i]的长度都是1len = 1;}// 如果有更大值,刷新maxLenif (len > maxLen) {maxLen = len;}}return maxLen;}
}

300. 最长递增子序列

方法:动态规划

思路:

  1. dp含义:dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度
  2. 递归公式:
    • 本意就是取出最大的dp[j]+1。通俗点来讲,就是接在哪个j后面,能有最大长度。
    • if (nums[i] > nums[j]) dp[i] = Math.max(dp[i], dp[j] + 1);
  3. 初始化:每一个nums[i]的子序列都至少是1,就是自己Arrays.fill(dp, 1);
  4. 遍历方向:正序
// 动态规划
class Solution {public int lengthOfLIS(int[] nums) {int n = nums.length;// dp含义:dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度int[] dp = new int[n];// 题目说n>=1,所以res至少也有1int res = 1;// 初始化:每一个nums[i]的子序列都至少是1,就是自己Arrays.fill(dp, 1);// 从1开始遍历for (int i = 1; i < n; i++) {// 从[0-i]中找,所以复杂度是O(n^2)for (int j = 0; j < i; j++) {if (nums[i] > nums[j]) {// 注意这里的max函数,本意不是为了比较dp[i]和dp[j]+1,而是为了取出本层最大的dp[i],因为j在遍历嘛// 本意就是取出最大的dp[j]+1。通俗点来讲,就是接在哪个j后面,能有最大长度dp[i] = Math.max(dp[i], dp[j] + 1);}}// 更新resres = Math.max(res, dp[i]);}return res;}
}

方法:贪心+二分

思路来自力扣官方题解

思路:

  • 考虑一个简单的贪心,如果我们要使上升子序列尽可能的长,则我们需要让序列上升得尽可能慢,因此我们希望每次在上升子序列最后加上的那个数尽可能的小。

  • 基于上面的贪心思路,我们维护一个数组 d[i] ,表示长度为 i 的最长上升子序列的末尾元素,用 len 记录目前最长上升子序列的长度,起始时 len 为 1,d[1]=nums[0]。

  • 设当前已求出的最长上升子序列的长度为 len(初始时为 1),从前往后遍历数组 nums,在遍历到 nums[i] 时:

    • 如果 nums[i]>d[len] ,则直接加入到 d 数组末尾,并更新 len=len+1;
    • 否则,在 d 数组中二分查找,找到第一个比 nums[i] 小的数 d[k] ,并更新 d[k+1]=nums[i]。
// 贪心 + 二分(时间复杂度nlogn)
class Solution {public int lengthOfLIS(int[] nums) {int n = nums.length;if (n == 0) {return 0;}int len = 1;int[] d = new int[n + 1];d[len] = nums[0];for (int i = 1; i < n; i++) {if (nums[i] > d[len]) {d[++len] = nums[i];} else {// 调用二分查找函数寻找合适的位置int pos = binarySearch(d, 1, len, nums[i]);d[pos + 1] = nums[i];}}return len;}// 二分查找函数,单独提取出来private int binarySearch(int[] d, int left, int right, int target) {int pos = 0; // 如果找不到说明所有的数都比 target 大,此时要更新 d[1],所以这里将 pos 设为 0while (left <= right) {int mid = left - ((left - right) >> 1);if (d[mid] < target) {pos = mid;left = mid + 1;} else {right = mid - 1;}}return pos;}
}

718. 最长重复子数组

注意,这题虽然说是“子数组”,但是实际上是按“子序列”理解。

子数组是可以重新排序的,子序列是不能改变原有的顺序的(但是可以跳过一些元素)

方法:暴力

思路:

每当nums1[i] == nums2[j]的时候,记录while(nums1[ii++] == nums2[jj++])的长度。

但是这个方法的时间复杂度很恐怖,去到O(n^3)

class Solution {public int findLength(int[] nums1, int[] nums2) {int maxLen = 0;int n1 = nums1.length;int n2 = nums2.length;for (int i = 0; i < n1; i++) {for (int j = 0; j < n2; j++) {if (nums1[i] == nums2[j]) {int ii = i;int jj = j;while (ii < n1 && jj < n2 && nums1[ii] == nums2[jj]) {ii++;jj++;}int len = ii - i;if (len > maxLen) {maxLen = len;}}}}return maxLen;}
}

方法:动态规划(二维DP数组)

思路:

  1. dp[i][j]含义:以下标i - 1为结尾的A,和以下标j - 1为结尾的B,的最长重复子数组长度
  2. 递推公式:
    • 前面的一位是相等的,那么dp[i][j]要等于dp[i - 1][j - 1] + 1,表明以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组的长度增加了1
    • if (nums1[i - 1] == nums2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
  3. 初始化:0
  4. 遍历顺序:正序
// 动态规划(二维DP数组)
class Solution {public int findLength(int[] nums1, int[] nums2) {int n1 = nums1.length;int n2 = nums2.length;// dp[i][j]含义:以下标i - 1为结尾的A,和以下标j - 1为结尾的B,的最长重复子数组长度int[][] dp = new int[n1 + 1][n2 + 1];int maxLen = 0;// 要从索引1开始遍历,到索引n才结束for (int i = 1; i <= n1; i++) {for (int j = 1; j <= n2; j++) {// 前面的一位是相等的,那么dp[i][j]等于前面的长度+1。(告诉后面到我这有多长重复)if (nums1[i - 1] == nums2[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;}// 刷新maxLenif (dp[i][j] > maxLen) {maxLen = dp[i][j];}}}return maxLen;}
}

方法:动态规划(一维DP数组)

思路:

《代码随想录》:

我们可以看出dp[i][j]都是由dp[i - 1][j - 1]推出。那么压缩为一维数组,也就是dp[j]都是由dp[j - 1]推出。

也就是相当于可以把上一层dp[i - 1][j]拷贝到下一层dp[i][j]来继续用。

此时遍历B数组的时候,就要从后向前遍历,这样避免重复覆盖

// 动态规划(一维DP数组)
class Solution {public int findLength(int[] nums1, int[] nums2) {int n1 = nums1.length;int n2 = nums2.length;// 因为把nums1的维度压缩了。所以要靠nums2作为dp// 所以要遍历nums1,nums2每层的状态要复用int[] dp = new int[n2 + 1];int maxLen = 0;for (int i = 1; i <= n1; i++) {// 因为要用到上一层的状态,所以要倒序遍历for (int j = n2; j > 0; j--) {if (nums1[i - 1] == nums2[j - 1]) {dp[j] = dp[j - 1] + 1;} else {dp[j] = 0; // 注意,不相等的话,要刷回0}// 刷新maxLenif (dp[j] > maxLen) {maxLen = dp[j];}}}return maxLen;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

支持 UMD 自定义组件与版本控制:从 Schema 到动态渲染

源码 ⸻ 支持 UMD 自定义组件与版本控制&#xff1a;从 Schema 到动态渲染 在低代码平台或可视化大屏 SDK 中&#xff0c;支持用户上传自定义组件 是一个必备能力。 而在 React 场景下&#xff0c;自定义组件通常以 UMD 格式 打包并暴露为全局变量。 本篇文章&#xff0c;我…

zookeeper3.8.4安装以及客户端C++api编译

服务端直接下载编译好的bin版本 Apache Download Mirrors C客户端需要编译库文件 zookeeper 3.8.4 使用与C API编译 - 丘狸尾 - 博客园 杂七杂八的依赖 sudo apt update sudo apt install -y \autoconf automake libtool libtool-bin m4 pkg-config gettext \cmake build-es…

使用行为树控制机器人(一) —— 节点

文章目录一、背景需求二、创建ActionNodes1. 功能实现1.1 头文件定义1.2 源文件实现1.3 main文件实现1.4 my_tree.xml 实现2. 执行结果三、 执行失败处理1. 添加尝试次数1.1 功能实现1.2 实验结果2. 完善异常处理2.1 多节点组合兜底2.2 实验结果使用行为树控制机器人(一) —— …

JavaScript Window Location

JavaScript Window Location JavaScript中的window.location对象是操作浏览器地址栏URL的一个非常有用的对象。它允许开发者获取当前页面的URL、查询字符串、路径等&#xff0c;并且可以修改它们来导航到不同的页面。以下是关于window.location的详细解析。 1. window.location…

Kubernetes生产环境健康检查自动化指南

核心脚本功能&#xff1a; 一键检查集群核心组件状态自动化扫描节点/Pod异常存储与网络关键指标检测风险分级输出&#xff08;红/黄/绿标识&#xff09;一、自动化巡检脚本 (k8s-health-check.sh) #!/bin/bash # Desc: Kubernetes全维度健康检查脚本 # 执行要求&#xff1a;kub…

消息队列系统测试报告

目录 一、项目背景 二、RabbitMQ介绍 1.什么是RabbitMQ&#xff1f; 2.RabbitMQ的工作流程是怎么样的&#xff1f; 3.项目设计 三、测试概述 MQ 测试目标&#xff1a; 测试用例统计&#xff1a; 核心模块测试详情及代码示例&#xff1a; 1. 数据库管理&#xff08;Da…

基于 Axios 的 HTTP 请求封装文件解析

import axios from "axios"; import { ElMessage } from "element-plus"; import store from "/store"; import router from "/router";// 创建axios实例 const service axios.create({baseURL: "http://localhost:8080/api&quo…

PowerDesigner生成带注释的sql方法

前提是name里面是有文字的&#xff1a; 方法开始&#xff1a; 第一步&#xff1a; Database → Edit Current DBMS → Script → Objects → Column → Add 把输出模板改成&#xff1a; %20:COLUMN% %30:DATATYPE%[.Z:[%Compressed%? compressed][ %NULLNOTNULL%][%IDENTITY…

猎板PCB:专业键盘PCB板解决方案供应商

猎板PCB深耕印刷电路板&#xff08;PCB&#xff09;制造领域&#xff0c;凭借前沿技术与深厚积淀&#xff0c;在键盘PCB板细分市场积极布局&#xff0c;致力于为不同客户提供多样化、高性能的键盘PCB板产品&#xff0c;满足多元需求。一、定义&#xff1a;键盘PCB板键盘PCB板&a…

基于 Spring Boot 的登录功能实现详解

在 Web 应用开发中&#xff0c;登录功能是保障系统安全的第一道防线。本文将结合实际代码&#xff0c;详细解析一个基于 Spring Boot 框架的登录功能实现&#xff0c;包括验证码生成、用户验证、Token 机制等关键环节。技术栈概览本登录功能实现涉及以下核心技术和组件&#xf…

vue+django 大模型心理学智能诊断评测系统干预治疗辅助系统、智慧心理医疗、带知识图谱

vuedjango 大模型心理学智能诊断评测系统干预治疗辅助系统、智慧心理医疗、带知识图谱文章结尾部分有CSDN官方提供的学长 联系方式名片 文章结尾部分有CSDN官方提供的学长 联系方式名片 关注B站&#xff0c;有好处&#xff01;编号:D003 pro基于大模型心理学问卷、智能诊断&…

【linux】企业级WEB应用服务器tomcat

一 WEB技术1.1 HTTP协议和B/S 结构操作系统有进程子系统&#xff0c;使用多进程就可以充分利用硬件资源。进程中可以多个线程&#xff0c;每一个线程可以被CPU调度执行&#xff0c;这样就可以让程序并行的执行。这样一台主机就可以作为一个服务器为多个客户端提供计算服务。客户…

【Unity优化】Unity多场景加载优化与资源释放完整指南:解决Additive加载卡顿、预热、卸载与内存释放问题

【Unity优化】Unity多场景加载优化与资源释放完整指南&#xff1a;解决Additive加载卡顿、预热、卸载与内存释放问题 本文将完整梳理 Unity 中通过 SceneManager.LoadSceneAsync 使用 Additive 模式加载子场景时出现的卡顿问题&#xff0c;分析其本质&#xff0c;提出不同阶段的…

B 树与 B + 树解析与实现

一、磁盘存储优化的核心逻辑 在大规模数据处理场景中&#xff0c;磁盘 I/O 效率是性能瓶颈的核心。磁盘访问具有以下特性&#xff1a; 随机访问成本高&#xff1a;磁头寻道时间&#xff08;Seek Time&#xff09;可达毫秒级&#xff0c;相比内存访问&#xff08;纳秒级&#…

MySQL 查询相同记录并保留时间最晚的一条

要在 MySQL 中查询相同记录并仅保留时间最晚的那一条&#xff0c;你可以使用以下几种方法&#xff1a;方法一&#xff1a;使用子查询和 GROUP BY假设你的表名为 your_table&#xff0c;时间字段为 create_time&#xff0c;其他用于判断记录相同的字段为 field1, field2 等&…

在 .NET Core 5.0 中启用 Gzip 压缩 Response

在 .NET Core 5.0 中启用 Gzip 压缩 Response 在 .NET Core 5.0 (ASP.NET Core 5.0) 中启用 Gzip 压缩主要通过响应压缩中间件实现。以下是详细配置步骤&#xff1a; 1. 安装必要的 NuGet 包 首先确保已安装响应压缩包&#xff1a; dotnet add package Microsoft.AspNetCore.Re…

[Oracle] TRUNC()函数

TRUNC() 是 Oracle 中一个多功能函数&#xff0c;主要用于对数值、日期进行截断操作1.TRUNC()函数用于数值处理语法格式TRUNC(number, decimal_places)参数说明number&#xff1a;要截断的数值 decimal_places&#xff1a;保留的小数位数(可选)&#xff0c;默认为0(截断所有小数…

GPT-oss:OpenAI再次开源新模型,技术报告解读

1.简介OpenAI 发布了两款开源权重推理模型 gpt-oss-120b 与 gpt-oss-20b&#xff0c;均采用 Apache 2.0 许可&#xff0c;主打在代理工作流中执行复杂推理、调用工具&#xff08;如搜索、Python 代码执行&#xff09;并严格遵循指令。120b 为 36 层 MoE 结构&#xff0c;活跃参…

python tcp 框架

目录 python tcp 框架 asyncio websockets python tcp 框架 asyncio import asyncio import json import timeclass TCPClient:def __init__(self, host, port, heartbeat_interval10):self.host hostself.port portself.heartbeat_interval heartbeat_intervalself.read…