秋招突击——6/22——复习{区间DP——加分二叉树,背包问题——买书}——新作{移除元素、实现strStr()}

本文主要是介绍秋招突击——6/22——复习{区间DP——加分二叉树,背包问题——买书}——新作{移除元素、实现strStr()},希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 引言
    • 复习
      • 区间DP——加分二叉树
        • 个人实现
      • 背包问题——买书
        • 个人实现
        • 参考实现
    • 新作
      • 移除元素
        • 个人实现
        • 参考思路
      • 找出字符串中第一个匹配项的下标
        • 个人实现
        • 参考实现
    • 总结

引言

  • 今天做了一个噩梦,然后流了一身汗,然后没起来,九点多才起床背书。十点钟才开始把昨天那道题题目过一遍,然后十一点才开始复习题目,为了不耽误下午的时间,所以这里的就单纯做已经做过的题目,主打一个有量,不在学习新的dp。

复习

区间DP——加分二叉树

  • 这道题差不多看了第二遍,第一次学的时候就蛮难的,不过有固定的编程范式,不过这里没想起来。提供一下之前的分析思路。

    • 第一次分析
    • 区间DP——合并石子
  • 之前做了两次,这次看看能不能一次过。

个人实现
  • 区间DP集合表示是f[i][j],
    • i是区间的左端点
    • j是区间的右端点,
  • 集合划分是区间的中间的,所以需要遍历枚举区间[i,j]中所有的区间分割点
  • 具体的代码流程如下
    • 列举区间长度
    • 列举区间左端点
    • 枚举的区间的分割点

实现问题

  • 区间长度的上下限有没有特殊情况,需不需要特殊考虑?如果区间长度为1,或者为n怎么办?
  • 特殊情况1
    • 区间长度为1,表示的左右子节是重合的,所以需要特殊考虑,当前情况是叶子节点
    • 区间长度就是1到n,不用考虑n+1,之前那个题目使用n+1是特殊情况,实际情况下,不需要使用使用n+1,而且这道题使用n+1也没有任何意义,那道题股票买卖题n+1一天的某种情况,是之前最大的。
#include <iostream>using namespace std;const int N = 35;
int f[N][N],n,rp[N][N];  // f表示区间的状态记录,r表示根节点的记录状态
int s[N];void dfs(int l,int r){if (l > r)  return ;int k = rp[l][r];cout<<k<<" ";if (k - 1 >= l) dfs(l,k - 1);if (k + 1 <= r) dfs(k + 1,r);
}int main(){cin>>n;for (int i = 1; i <= n; ++i) {cin>>s[i];s[i] += s[i - 1];}// 区间DPfor (int len = 1; len <= n; ++len) {// 列举区间左端点for (int l = 1; l + len <= n; ++l) {// 计算区间的右端点int r = l + len  - 1;// 列举区间的分割点for (int k = l; k <= r; ++k) {if(看== 1int temp;if (k == l){// 左端点为空temp = (s[k] -s[k - 1]) + f[k + 1][r];}else if(k == r){// 右子树为空temp = (s[k] -s[k - 1]) + f[l][k - 1];}else{// 左右子树都不为空temp = (s[k] -s[k - 1]) + f[k + 1][r] * f[l][k - 1];}// 比较确定最大值的并进行记录if (f[l][r] < temp) {rp[l][r] = k;f[l][r] = temp;}}}}cout<<f[0][n];dfs(0,n);return f[0][n];}

修改之后的如下

  • 其实这里有两个地方还是可以修改的,左右节点的情况是可以特殊讨论和考虑的。
#include <iostream>using namespace std;const int N = 35;
int f[N][N],n,rp[N][N];  // f表示区间的状态记录,r表示根节点的记录状态
int s[N];void dfs(int l,int r){if (l > r)  return ;int k = rp[l][r];cout<<k<<" ";if (k - 1 >= l) dfs(l,k - 1);if (k + 1 <= r) dfs(k + 1,r);
}int main(){cin>>n;for (int i = 1; i <= n; ++i) {cin>>s[i];}// 区间DPfor (int len = 1; len <= n; ++len) {// 列举区间左端点for (int l = 1; l + len <= n; ++l) {// 计算区间的右端点int r = l + len  - 1;if (l == r) f[l][r] = s[l],rp[l][r] = l;else// 列举区间的分割点for (int k = l; k <= r; ++k) {int temp;if (k == l){// 左端点为空temp = s[k] + f[k + 1][r];}else if(k == r){// 右子树为空temp = s[k] + f[l][k - 1];}else{// 左右子树都不为空temp = s[k] + f[k + 1][r] * f[l][k - 1];}// 比较确定最大值的并进行记录if (f[l][r] < temp) {rp[l][r] = k;f[l][r] = temp;}}}}cout<<f[0][n];dfs(0,n);return f[0][n];}

背包问题——买书

在这里插入图片描述

  • 标准的背包问题
个人实现
  • 标准的背包问题,但是是计算方案数量的,而且会存在重复方案的问题,需要去除重复?是一个问题,并不是那么好去掉重复的。
  • 但是如果一开始是按照顺序进行购买的,后续只会增加更贵的物品,我应该如何进行计算?
  • 方案数应该怎么计算?直接求,整个矩阵的累加和就行了。
  • 注意,这里有一个,所有书全部用来购买书,手里不能有剩钱。

这是一个重复背包问题,属实不会弄,该想想怎么弄了!

#include <iostream>using namespace std;const int N = 10010;
int f[N],n;
int w[4] = {10,20,50,100};int main(){cin>>n;int sum = 0;if (n % 10 != 0) cout<<0<<endl;else {for (int i = 0; i < 4; ++i) {for (int j = n; j >= w[i]; j--) {f[j] = f[j - w[i]] + f[j];}}cout << sum;}
}
参考实现
  • 参考作者:一只野生彩色铅笔
    链接:https://www.acwing.com/solution/content/52967/
    来源:AcWing
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在这里插入图片描述

  • 下述方法还是很朴素的,确实如此,这道题暂时先跳过,这个方案转换公式是想到了,但是没有写出来。关键是他还有优化,下次再来吧,还要看redis,没那么多时间。
#include <iostream>using namespace std;const int N = 5, M = 1010;int n = 4, m;
int v[N] = {0, 10, 20, 50, 100};
int f[N][M];int main()
{//inputcin >> m;//dpf[0][0] = 1;for (int i = 1; i <= n; ++ i){for (int j = 0; j <= m; ++ j){for (int k = 0; v[i] * k <= j; ++ k){f[i][j] += f[i - 1][j - v[i] * k];}}}//outputcout << f[n][m] << endl;return 0;
}

新作

移除元素

题目链接
在这里插入图片描述
在这里插入图片描述

个人实现

重点

  • 原地移除所有等于val的元素,后续的元素向前移动
  • 保证前k个元素是不等于val的,并且原来的顺序不变
  • nums的其余元素和nums的大小并不重要

实现思路

  • 两个指针,一个从前往后,一个从后往前
  • 从前往后的负责遍历对应的数组,判定当前的元素是否等于val,然后从后往前的元素负责将不相等的元素移动到从前往后的索引下方。

在这里插入图片描述

class Solution {
public:int removeElement(vector<int>& nums, int val) {int i = 0,r = nums.size() - 1;for (; i <= r ; ++i) {if (nums[i] == val) {while (r >= 0 && nums[r] == val) r--;if (i <= r ) nums[i] = nums[r],r--;else return i;}}return i;}
};

总结

  • 做是做出来了 ,但是说实话,稀碎,明明是道简单的题目,但是还是调了很久,思路很快就想到了,但是总是遇到各种各样的bug。
  • 有以下几个细节需要注意
    • 凡是涉及到数组索引的,都要进行检测,防止数组越界。这次在遍历右指针的时候,有好几个地方都没有对指针进行检查,导致不断报错溢出,很难受。
参考思路
  • 这个思路太暴力了,时间复杂度比我的高,完整遍历了整个数组。不对,其实我也是遍历了整个数组,不过我是双指针。而且是反向的,不行,这样完全没有必要。

  • 就是两个指针

    • idx表示实际的指针,只有不同的时候才会赋值并且递增
    • i表示遍历的指针,如果不同就执行赋值,如果相同就跳过。
  • 老是会把问题想的太复杂

class Solution {
public:int removeElement(vector<int>& nums, int val) {int idx = 0;for (int i = 0; i < nums.size(); ++i) {if (nums[i] != val){nums[idx] = nums[i];idx ++;}}return idx;}
};

找出字符串中第一个匹配项的下标

  • 题目链接

在这里插入图片描述

个人实现

重点

  • 第一个字符串中找出第二个字符串的第一个匹配项目的下标
    • 第二个字符串是一个子串,然后在第一个字符串中找到字串出现的第一个索引位置

思路实现

  • 别把这个问题想的太复杂,这是一道简单题,并不是中等题,所以怎么想就怎么实现。
  • 最直白的方式,就是两个指针进行遍历

在这里插入图片描述

class Solution {
public:int strStr(string h, string n) {bool f;for (int i = 0; i < h.size(); ++i) {f = true;for (int j = 0; j < n.size(); ++j) {if (h[i + j] != n[j])   {f = false;break;   }}if (f)  return i;}return -1;}
};
参考实现
  • 跳过吧,这个是用KMP算法的模板题,没有必要!
  • 这里仅仅贴一个代码就行了。
class Solution {
public:int strStr(string s, string p) {if (p.empty()) return 0;int n = s.size(), m = p.size();s = ' ' + s, p = ' ' + p;vector<int> next(m + 1);for (int i = 2, j = 0; i <= m; i ++ ) {while (j && p[i] != p[j + 1]) j = next[j];if (p[i] == p[j + 1]) j ++ ;next[i] = j;}for (int i = 1, j = 0; i <= n; i ++ ) {while (j && s[i] != p[j + 1]) j = next[j];if (s[i] == p[j + 1]) j ++ ;if (j == m) return i - m;}return -1;}
};

作者:yxc
链接:https://www.acwing.com/activity/content/code/content/347914/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

总结

  • 今天两道简单的leetcode做完了,发现自己容易把问题想复杂,完全没有意义,简单题,怎么想怎么来。
  • 然后算法题复习题,又被背包问题给难住了,实际上能够写出状态转移方程,但是觉得有点麻烦,那个完全背包问题就划水划过去了。明天重点看一下这道题,然后再随便找一道区间DP的新题。

这篇关于秋招突击——6/22——复习{区间DP——加分二叉树,背包问题——买书}——新作{移除元素、实现strStr()}的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089365

相关文章

linux生产者,消费者问题

pthread_cond_wait() :用于阻塞当前线程,等待别的线程使用pthread_cond_signal()或pthread_cond_broadcast来唤醒它。 pthread_cond_wait() 必须与pthread_mutex 配套使用。pthread_cond_wait()函数一进入wait状态就会自动release mutex。当其他线程通过pthread

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

问题:第一次世界大战的起止时间是 #其他#学习方法#微信

问题:第一次世界大战的起止时间是 A.1913 ~1918 年 B.1913 ~1918 年 C.1914 ~1918 年 D.1914 ~1919 年 参考答案如图所示

可视化实训复习篇章

前言: 今天,我们来学习seaborn库可视化,当然,这个建立在Matplotlib的基础上,话不多说,进入今天的正题吧!当然,这个是《python数据分析与应用》书中,大家有需求的可以参考这本书。 知识点: Matplotlib中有两套接口分别是pyplot和pyylab,即绘图时候主要导入的是Matplotlib库下的两个子模块(两个py文件)matplotlib.pyplot和matp

2024.6.24 IDEA中文乱码问题(服务器 控制台 TOMcat)实测已解决

1.问题产生原因: 1.文件编码不一致:如果文件的编码方式与IDEA设置的编码方式不一致,就会产生乱码。确保文件和IDEA使用相同的编码,通常是UTF-8。2.IDEA设置问题:检查IDEA的全局编码设置和项目编码设置是否正确。3.终端或控制台编码问题:如果你在终端或控制台看到乱码,可能是终端的编码设置问题。确保终端使用的是支持你的文件的编码方式。 2.解决方案: 1.File -> S

vcpkg安装opencv中的特殊问题记录(无法找到opencv_corexd.dll)

我是按照网上的vcpkg安装opencv方法进行的(比如这篇:从0开始在visual studio上安装opencv(超详细,针对小白)),但是中间出现了一些别人没有遇到的问题,虽然原因没有找到,但是本人给出一些暂时的解决办法: 问题1: 我在安装库命令行使用的是 .\vcpkg.exe install opencv 我的电脑是x64,vcpkg在这条命令后默认下载的也是opencv2:x6

22.手绘Spring DI运行时序图

1.依赖注入发生的时间 当Spring loC容器完成了 Bean定义资源的定位、载入和解析注册以后,loC容器中已经管理类Bean 定义的相关数据,但是此时loC容器还没有对所管理的Bean进行依赖注入,依赖注入在以下两种情况 发生: 、用户第一次调用getBean()方法时,loC容器触发依赖注入。 、当用户在配置文件中将<bean>元素配置了 lazy-init二false属性,即让

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

2390.从字符串中移除星号

给你一个包含若干星号 * 的字符串 s 。 在一步操作中,你可以: 选中 s 中的一个星号。 移除星号左侧最近的那个非星号字符,并移除该星号自身。 返回移除 所有 星号之后的字符串。 注意: 生成的输入保证总是可以执行题面中描述的操作。 可以证明结果字符串是唯一的。 示例 1: 输入:s = “leet**cod*e” 输出:“lecoe” 解释:从左到右执行移除操作: 距离第 1 个

问题-windows-VPN不正确关闭导致网页打不开

为什么会发生这类事情呢? 主要原因是关机之前vpn没有关掉导致的。 至于为什么没关掉vpn会导致网页打不开,我猜测是因为vpn建立的链接没被更改。 正确关掉vpn的时候,会把ip链接断掉,如果你不正确关掉,ip链接没有断掉,此时你vpn又是没启动的,没有域名解析,所以就打不开网站。 你可以在打不开网页的时候,把vpn打开,你会发现网络又可以登录了。 方法一 注意:方法一虽然方便,但是可能会有