最长递增子序列 详解 CPP

目录

  • 前言
  • 思路梳理
    • 题解最优思路
  • 我的思路
    • 思路一 考虑连续 对一半 ×
    • 思路二 基于思路一的优化 ×
    • 思路三 基于思路二的优化 √ 通过了但是效率太低
  • 我的代码

前言

今天继续做动态dp的第三题,最大子序和,昨天做最大连续子数组的和已经有一些写状态转移方程的经验了,今天自己想了一个思路一。

思路梳理

题解最优思路

写到这里我想惊叹一下数学语言的魅力,因为我虽然想清楚了但是却表达不清楚。一个数学公式代替了我的一大坨废话。
在这里插入图片描述

在这里插入图片描述
这里最大的坑在于,状态转移的前一个状态需要满足两个条件。从我自己的思路三优化到这里也并不复杂,感觉我自己的思路就好像是先把水煮开再一起下饺子,官方思路是冷水的时候我就可以把饺子放下去慢慢煮了。很多判断可以在遍历的时候就做了
以下是代码:

int max_subArr_Ascending_order_optimize_Original(vector<int> Arr) {vector<int> resArr(Arr.size());for (int i = 0; i < Arr.size(); i++) {//先把最差的情况确定好,最差的情况也不过就是1了resArr[i] = 1;//然后再循环左边比它小的最大值for (int j = 0; j < i; j++) {if (Arr[j] < Arr[i]) {resArr[i] = max(resArr[j] + 1, resArr[i]);}}}return *max_element(resArr.begin(),resArr.end());
}

我的思路

思路一 考虑连续 对一半 ×

跟昨天的类似,也是以子数组的最后一个元素的位置作为标记。首先我找到最大的连续升数组,然后再在这个基础上加上前面的不连续的。但是很遗憾,这个思路只通过了一半的测试用例,想想看确实是有很大问题的。不应该考虑连续,连续的bug太大了。
在这里插入图片描述

class Solution {
public:int lengthOfLIS(vector<int>& Arr) {int res = 1;vector<int> resArr(Arr.size());resArr[0] = 1;int left_max_location;for (int i = 1; i < Arr.size(); i++) {// 首先找到左边比它小,且最大的元素left_max_location = search_left_less_than(i, Arr, resArr);if (left_max_location == -1) {resArr[i] = 1;} else {resArr[i] = left_max_location + 1;}if (resArr[i] >= res) {res = resArr[i];}}return res;}int search_left_less_than(int i, vector<int>& Arr, vector<int>& resArr) {// 如果这个元素比前面的所有元素都小的话,就返回-1if (*min_element(Arr.begin(), Arr.begin() + i) >= Arr[i]) {return -1;}// 重新设置一个数组,把所有值比i元素小的都存进去。vector<int> left_less(i);for (int j = i - 1; j >= 0; j--) {if (Arr[j] < Arr[i]) {left_less.push_back(resArr[j]);}}// 存好了之后我现在就找一个最大值了int left_location_max =*max_element(left_less.begin(), left_less.end());// 直接把这个最大值给返回出去return left_location_max;}
};

思路二 基于思路一的优化 ×

思路二我继续来考虑怎么去设置这个状态转移方程,以i位置结束的连续递增数组,它和次长的递增数组没有 物理空间 上 紧挨着的 特征了。因此我觉得它应该考虑的是 数组左边 第一个比它小的元素值,在它的基础上+1。如此我们可以得到一下总结:

  1. 我们给最大子数组设置标签:子数组在i元素处结尾,设置一个resArr来存储以这个结尾的最大递增长度。
  2. 考虑初始条件:resArr[0]初始化为1;
  3. 状态转移方程:resArr[i]等于resArr[j]+1 ( j 为 i 的左边第一个小于自己本身元素的位置) 如果这个元素是从0到i最大的,就直接令resArr=1;

这个思路也是错的,并不是数组左边第一个值比它小的元素,而是需要满足①比它小 ②以这个位置结束的递增子数组的长度值要是最大的

思路三 基于思路二的优化 √ 通过了但是效率太低

修改了之后,发现我的解答还是错误,一行行debug发现是我的函数用的有问题:

vector函数自己有丰富的方法,可以直接帮我们找到数组里面的最大值,方法是max_element(要引入algorithm库),但是它其实有点类似于python的切片,函数的参数要给出vecotor的迭代器(Arr.begin(),Arr.end()),我的错误就在于这个函数他的索引对象是从参数一开始到参数二的前一个,(Arr.end()其实就是指向vector最后一个参数的下一个)。

在这里插入图片描述
修改之后,测试都通过了,但是超出内存限制了。

这个其实是因为我在传递函数的时候没有使用引用,没使用引用就会在调用的时候复制一遍占用大量内存。

改完之后,终于通过了。。。但是依旧感觉好菜哈哈哈哈。
在这里插入图片描述

class Solution {
public:int lengthOfLIS(vector<int>& Arr) {int res = 1;vector<int> resArr(Arr.size());resArr[0] = 1;int locate = 0;int left_max_location;for (int i = 1; i < Arr.size(); i++) {//首先找到左边比它小,且最大的元素left_max_location = search_left_less_than(i, Arr, resArr);if (left_max_location == -1) {resArr[i] = 1;}else {resArr[i] = left_max_location + 1;}if (resArr[i] >= res) {res = resArr[i];locate = i;}}return res;}int search_left_less_than(int i, vector<int> &Arr, vector<int> &resArr) {//如果这个元素比前面的所有元素都小的话,就返回-1if (*min_element(Arr.begin(), Arr.begin() + i ) >= Arr[i]) {return -1;}vector<int> x = resArr;//重新设置一个数组,把所有值比i元素小的都存进去。vector<int> left_less(i, 0);for (int j = i - 1; j >= 0; j--) {if (Arr[j] < Arr[i]) {left_less[j] = resArr[j];}}//存好了之后我现在就找一个最大值了int left_location_max = *max_element(left_less.begin(), left_less.end());//直接把这个最大值给返回出去return left_location_max;}
};

我的代码

#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;class solution {
public://int max_subArr_sum(vector<int> Arr) {//    int res = Arr[0];//    vector<int> resArr(Arr.size());//    resArr[0] = res;//    for (int i = 1; i < Arr.size(); i++) {//        /*if (resArr[i - 1] + Arr[i] > resArr[i - 1]) {//            resArr[i] = resArr[i - 1] + Arr[i];//        }//        else {//            resArr[i] = resArr[i - 1];//        }//        if (resArr[i] > res) {//            res = resArr[i];//        }*///        if (resArr[i - 1] > 0) {//            resArr[i] = resArr[i - 1] + Arr[i];//        }//        else {//            resArr[i] = Arr[i];//        }//        if (resArr[i] > res) {//            res = resArr[i];//        }//    }//    return res;//}//int max_subArr_Ascending_order(vector<int> Arr) {//    int res = 1;//    vector<int> resArr(Arr.size());//    resArr[0] = 1;//    int locate = 0;//    for (int i = 1; i < Arr.size(); i++) {//        if (Arr[i - 1] >= Arr[i]) {//            resArr[i] = 1;//        }//        else {//            resArr[i] = resArr[i - 1] + 1;//        }//        if (resArr[i] >= res) {//            res = resArr[i];//            locate = i;//        }//    }//    int current_max = Arr[locate - resArr[locate] + 1];//    for (int i = locate - 1; i >= 0; i--) {//        if (Arr[i] < current_max) {//            res++;//            current_max = Arr[i];//        }//    }//    return res;//}int max_subArr_Ascending_order_optimize(vector<int> Arr) {int res = 1;vector<int> resArr(Arr.size());resArr[0] = 1;int left_max_location;for (int i = 1; i < Arr.size(); i++) {//首先找到左边比它小,且最大的元素left_max_location = search_left_less_than(i, Arr, resArr);if (left_max_location == -1) {resArr[i] = 1;}else {resArr[i] = left_max_location + 1;}if (resArr[i] >= res) {res = resArr[i];}}       return res;}int search_left_less_than(int i, vector<int> &Arr, vector<int> &resArr) {//如果这个元素比前面的所有元素都小的话,就返回-1if (*min_element(Arr.begin(), Arr.begin() + i ) >= Arr[i]) {return -1;}//重新设置一个数组,把所有值比i元素小的都存进去。vector<int> left_less(i);for (int j = i - 1; j >= 0; j--) {if (Arr[j] < Arr[i]) {left_less.push_back(resArr[j]);}}//存好了之后我现在就找一个最大值了int left_location_max = *max_element(left_less.begin(), left_less.end());//直接把这个最大值给返回出去return left_location_max;}int max_subArr_Ascending_order_optimize_Original(vector<int> Arr) {vector<int> resArr(Arr.size());for (int i = 0; i < Arr.size(); i++) {//先把最差的情况确定好,最差的情况也不过就是1了resArr[i] = 1;//然后再循环左边比它小的最大值for (int j = 0; j < i; j++) {if (Arr[j] < Arr[i]) {resArr[i] = max(resArr[j] + 1, resArr[i]);}}}return *max_element(resArr.begin(),resArr.end());}
};int main() {solution s;vector<int> Arr = { 3,1,2 };int x = s.max_subArr_Ascending_order_optimize(Arr);cout << x << endl;
}

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

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

相关文章

2010年认证杯SPSSPRO杯数学建模D题(第一阶段)服务网点的分布全过程文档及程序

2010年认证杯SPSSPRO杯数学建模 D题 服务网点的分布 原题再现&#xff1a; 服务网点、通讯基站的设置&#xff0c;都存在如何设置较少的站点&#xff0c;获得较大效益的问题。通讯基站的覆盖范围一般是圆形的&#xff0c;而消防、快餐、快递服务则受到道路情况和到达时间的限…

这份走心的母亲节礼物清单,请查收!

老舍在《我的母亲》中写道&#xff1a;“人&#xff0c;活到八九十岁&#xff0c;有母亲在&#xff0c;便可以多少还有点孩子气。失了慈母便像花插在瓶子里&#xff0c;虽然还有色有香&#xff0c;却失去了根。有母亲的人&#xff0c;心里是安定的。”母亲&#xff0c;对我们每…

Git详解之五:分布式Git

为了便于项目中的所有开发者分享代码&#xff0c;我们准备好了一台服务器存放远程 Git 仓库。经过前面几章的学习&#xff0c;我们已经学会了一些基本的本地工作流程中所需用到的命令。接下来&#xff0c;我们要学习下如何利用 Git 来组织和完成分布式工作流程。 特别是&#…

搭建知识库必备:12个开源 Wiki 软件工具盘点

在任何成功的公司中&#xff0c;部门间的知识共享是至关重要的。如果没有一个简单的信息交流方法&#xff0c;团队怎样才能有效合作呢&#xff1f;Wiki软件提供了一种创建、组织及在全公司范围内分享知识的直接方法。但是&#xff0c;哪一种Wiki软件是最佳的选择呢&#xff1f;…

论文笔记:PRIVACY ISSUES IN LARGE LANGUAGE MODELS: A SURVEY

1 intro 1.1 motivation 2022年11月ChatGPT的推出引起了全球轰动&#xff0c;推动了人工智能研究、初创企业活动以及大型语言模型&#xff08;LLM&#xff09;的消费者采用。到2023年底&#xff0c;LLM的进展持续加速&#xff0c;但人们普遍认为&#xff0c;尽管LLM带来了变革…

Day65:代码随想录训练营总结

两个月的算法训练营之旅圆满落幕&#xff0c;回首这段时光&#xff0c;我深感自己错过了许多早日成长的机会&#xff0c;如今不禁懊悔没有更早地报名参与。 这段充实的日子里&#xff0c;我遵循着训练营精心设计的计划&#xff0c;攻克了上百道力扣题目。从最初对编程语法的生…

【C++】Vector详解

Vector是什么&#xff1f; vector是C&#xff08;STL&#xff09;中的一种序列容器Vector是一个动态数组&#xff0c;内存空间是连续的&#xff0c;支持随机访问&#xff0c;支持迭代器访问 Vector代码实现 变量指向 代码初始化 #include<iostream> using namespace …

【教程向】从零开始创建浏览器插件(四)探索Chrome扩展的更多常用API

探索Chrome扩展的更多常用API 在Chrome扩展开发中&#xff0c;除了最基础的API外&#xff0c;Chrome还提供了一系列强大的API&#xff0c;允许开发者与浏览器的各种功能进行交互。本文将介绍其中几个常用的API&#xff0c;并提供详细的示例代码帮助您开始利用这些API。 书签…

XSS-Labs 靶场通过解析(下)

前言 XSS-Labs靶场是一个专门用于学习和练习跨站脚本攻击&#xff08;XSS&#xff09;技术的在线平台。它提供了一系列的实验场景和演示&#xff0c;帮助安全研究人员、开发人员和安全爱好者深入了解XSS攻击的原理和防御方法。 XSS-Labs靶场的主要特点和功能包括&#xff1a;…

VMware虚拟机中Linux系统奔溃,怎么办?

一大早启动虚拟机准备开始工作&#xff0c;却遭遇到Linux系统崩溃&#xff0c;屏幕上显示以下错误提示&#xff1a; 这段文本看起来是来自系统引导时的日志信息&#xff0c;提到了一些关于文件系统的问题和建议。根据这段信息&#xff0c;似乎 /dev/sda1 分区中的文件系统存在一…

STM32入门周边知识(为什么要装MDK,启动文件是什么,为什么要配置时钟等等)

目录 MDKMDK与C51共存为什么要安装MDK 启动文件是什么&#xff0c;为什么要添加许多文件为什么要添加头文件路径为什么是寄存器配置魔术棒中的define为什么必须先配置时钟杂例 MDK MDK与C51共存 在最开始学习51单片机的时候&#xff0c;当时安装keil的时候&#xff0c;认为就是…

### 【数据结构】线性表--顺序表(二)

文章目录 1、什么是线性表2、线性表的基本操作3、顺序表3.1、顺序表的定义3.2、顺序表的实现方式&#xff1a;静态分配3.3、顺序表的实现方式&#xff1a;动态分配3.4、顺序表的特点3.5、顺序表的初始化与插入操作3.6、顺序表的删除与查询 1、什么是线性表 ​ 线性表是具有相同…