day44 | 子序列问题

今天主要是

最长公共子序列 和 判断子序列这两类问题的区分。

在公共子序列问题中有不相等的时候 dp[i][j]=max(dp[i-1][j],dp[i][j-1])

和子系列不相等的时候却是 dp[i][j] = dp[i][j-1]

因为判断子系列问题是给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

实际上我们转换的问题是s 字符串在在 t 字符串中最长距离。 因此不相等的时候要保持 s 字符串的完整

在公共子序列问题中我们求得是 s 和 t 中最大的公共长度,无法确保当前是 s 保持完整还是 t 保持完整才能求得最终的最大公共长度。

全部评论

相关推荐

Git的工作流程通常包括以下几个步骤:https://www.nowcoder.com/issue/tutorial?zhuanlanId=Mg58Em&uuid=f818c6d22c98401682f8662612b9e57f克隆(Clone):首先,通过克隆一个远程仓库到本地,创建一个本地仓库的副本。这样可以在本地进行开发和修改。添加和修改(Add and Modify):在本地仓库中进行代码的添加和修改。开发者可以通过添加新文件、修改现有文件或删除文件来进行开发工作。暂存(Stage):将修改的文件添加到暂存区(也称为索引),准备提交到版本库。暂存区相当于一个缓冲区,用于存放即将提交的修改。提交(Commit):将暂存区的修改提交到版本库。每次提交都会生成一个唯一的提交记录,包含了修改的详细信息,如作者、时间戳和提交消息。推送(Push):将本地的提交推送到远程仓库,与团队成员共享代码。推送操作将本地的提交同步到远程仓库,使得其他人可以看到和使用这些修改。拉取(Pull):从远程仓库拉取最新的代码更新到本地仓库。当其他人推送了新的修改到远程仓库时,开发者可以通过拉取操作获取这些更新。合并(Merge):将不同分支的修改合并到一起。当开发者在不同的分支上进行并行开发时,可以使用合并操作将分支的修改合并到主分支或其他分支上。冲突解决(Conflict Resolution):当多个分支对同一文件进行了不同的修改时,可能会发生冲突。开发者需要手动解决这些冲突,选择保留哪些修改或进行修改的合并。这些步骤构成了Git的基本工作流程。通过这个工作流程,开发者可以有效地管理代码的版本、协作开发和跟踪修改历史。
点赞 评论 收藏
分享
能接触到的常见问法:项目中有用到什么设计模式?(前端更多点)重构使用了什么设计模式?(如果你项目强调了重构一般会问)说说对 XX 模式的理解?(个人接触过的是单例和工厂,这两个比较多)有接触到哪些?实际用到过哪些?(通用)除了这些,还有一些不常见的进阶和基础问法,这些直接在下面整理--设计模式这个主题还挺玄乎的,个人直观体验是,自己日常实习那段时间问得挺频繁的,可能是因为没啥好问的。找暑期实习的时候就问的少了。可能设计模式的定位还真是,个人体验也是,没有大量实践注定没有深刻的理解,对校招生的要求不会那么高吧。所以我感觉一般策略还是要强调,能想到什么说什么,展示自己对设计模式有一个基本理解,有刻意去考虑使用设计模式这种感受。作为面试 fw 就不多说了,这里就自己能想到什么就整理什么呢。参考价值不大,可能更多的还是要结合自己项目。--OOP 有哪些设计原则?如何理解?(这个可能 cpp 问的比较多,go 倒是不常问)● 封装。定义是我们通过向对象传递消息来直接执行方法,隐藏方法细节,而不是面向过程那样直接展示方法。这个基础上扩展,才有了私有方法变量这种进一步的封装。● 继承。继承就是字面继承一个类是属性方法,实现复用和多态。● 多态(比较常问),定义是对象在不同条件在统一接口下有不同的行为。go 主要通过接口实现,java 和 cpp 也都是分解通过继承和接口/虚函数实现。  ○ cpp 函数重载是一种「编译时多态」,不太符合传统理念上的多态。  ○ 策略模式的设计模式,同一对象在不同环境下使用不同算法,就是一种常见的多态设计。比如 orm 框架适配多种存储策略,cpp 排序 stl 适配多种排序算法。如何理解设计模式和设计原则?● 区别简单来说,设计原则是一些比较抽象的知道原则和方向,设计模式则是一些具体的时间。● 设计模式分为创建型、结构型、行为型三种。● 五大设计原则 SOLID:  ○ 单一职责:一个类只负责一个功能,具体一般也扩展到一个模块只负责一类功能,一个函数只负责一件事情。  ○ 开闭:对扩展开放,对修改关闭。这个一旦沾了企业开发确实就接触的挺多,说到这个想起我上段实习就是上去就把代码给重构了被臭骂了一顿。总之这个的意思简单说现有的代码不应该乱改,影响稳定影响线上功能要回归测试。好的做法是,有接口留够扩展性在那(这个需要之前设计的人有实力),你的想做的新的需求应该是在现有的基础上去做扩展。还有一个常见的例子是,假设你有一个新需求,你现在有一个线上接口可以通过加参数来实现,这种情况更好的做法是另起一个新接口,因为你改改逻辑就顶天了,改函数签名影响可能就比预想的要大很多了。  ○ 里氏替换:子类必须能替换父类,保持行为不变。这个 go 里边用不到。覆写不违反 lsp 原则,只要不改变预期行为。  ○ 接口隔离:客户端不应该知道他不知道的功能。在 go 里面能考虑的地方还挺多的。首先接口设计上,接口要尽量小,去发现接口而不是事先创造接口。其次,go 里面接口独特的机制是隐式实现,所以双端同时使用接口不会有循环依赖问题,所以我们常见的一种实现是服务端负责完整抽象,客户端单独做他的部分抽象。这个就是经常说的,在 go 里面“避免完成生产侧的接口”  ○ 依赖倒置:定义是上层不应该依赖下层,而都应该依赖抽象。抽象不依赖细节,细节以应该依赖抽象。设计目的是为了创造耦合性低的依赖关系,所以 DIP 往简单了说就是解耦。此外控制反转,IoC,一种具体实现 DIP 的设计模式,不手动控制对象把控制权交给容器或者框架,其实反面例子就是面向过程的手动控制对象的创建、行动相关操作。依赖注入DI,一个具体的行为,也可以说 IoC 的实现方法之一但是不只是在 ioc 里面用到,就是把对象直接作为参数传入另一个流程的一个写法而已,例子有很多,比如 vue 里边就可以注入全局变量来解决深参数传递的问题。● 五原则回顾,开闭和依赖倒置比较常问。这两个是有点像的,不过区别也很明显,虽然都可以借助接口实现,不过一个目的是扩展一个目的是为了解耦。常用的几个设计模式?● 工厂:一些定义和典型实现是,专门用一个工厂类来封装创建对象的逻辑,类的创建延迟到子类。好处是封装、低耦合(创建的逻辑是独立的内聚的)、便于扩展(要增加新的创建方法的话,直接替换掉原来的工厂方法调用就好了)。● 单例:目的是全局就是只能只应该唯一实例,否则并发问题或者管理混乱。例子像是 logger,confger,连接池,cache。然后恶汉懒汉 doublecheck 确保能单例实例化。你 go 项目里会用到设计模式?(Java 废物,Java 那块的 aop,ddd 就不整理了)不多说,直接提供例子,这种一般你没实际写过,能答出来面试官也不会感兴趣,所以其实一些过于抽象的模式,像是代理、桥接也就不必说了● NewXXX()是一种简单工厂模式● sync.Once()实现单例● 注册模式:实现全局 init 对象到一个 map 里● 责任链模式,我们不管请求最后会怎么样,没法解决的问题往下传,“丢锅”:gin 的中间件机制。● WithOption、可变参数、函数闭包 实现 选项模式 https://goplay.tools/snippet/xpnL6BhCsJa● 建造者模式就是比方我们用个 resty类似的 http 库,来发一个请求 setHeader● 策略模式比较常见,interface 多种算法实现都是策略模式,比方说多种灰度方案限流方案数据库连接方案偶见的设计原则开放性场景题:假如有一个历史包袱很重的项目丢给你重构,你会考虑到哪些设计原则和设计模式?(这个很考验积累了,我能做到的只能是分享这个问题和目前的浅见解了,欢迎探讨)● 没话说就是上面的原则逐个说一遍就好了● 肯定要强调的是模块化,高内聚低耦合,原因能想到的也围绕一些常用的点说:可维护性、复用性、扩展性、稳定性、简单性。有点八股性质了,具体还是看经验结合例子说。不过能想到这些角度感觉也是有意义的。--卡着实习 ddl 昨天实在没写完,精力管理确实重要。决策消耗心智大概到极限了,优化空间在于把实习的事情看得更轻一点,都打算跑了根本不用在意那么多。不过实际做起来还是很难协调,实操性大一点的地方还是在于尽量把排期铺开,分不出时间就延期。中断一天,重新开始#每天一篇简单博客 day2-1 (个人打卡,欢迎监督
查看8道真题和解析
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务