当前位置: 首页 > news >正文

数据结构与算法 -- 子序列问题

一、子序列问题

        子数组问题是连续的,而子序列问题是不连续的。比如说字符串 “I wanna keep a giraffe in my backyard” 的一种子序列就可以是 “Igbackd”。 子序列不再要求答案是一个连续的串。一个字符串的子序列,是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。举个例子,“ace” 是 “abcde” 的子序列,但是 “aec” 就不是 “abcde” 的子序列。

二、最长回文子序列

1、问题描述

问题:给定一个字符串 s ,找到其中最长的回文子序列,并返回该序列的长度。可以假设 s 的最大长度为 1000。 


示例1:

输入:"asssasms"
输出:5
解释:一个可能的最长回文子序列为 "sssss",另一种可能的答案是 "asssa"。

2、算法分析

1)初始化状态

        单个字符一定是它自己的回文;

2)状态参数

        一个是起始位置,另一个是结束位置。在算法的执行过程中,起始和结束位置是变化的,因此它们是状态参数。 

3)决策

        当前子问题的答案就是通过前面的子问题 ➕ 当前的决策推导出来的。当前的决策就是:计算出向子问题的两边分别扩充一个元素后得到的答案。 

4)备忘录

        DP[i][j],其对应的值是字符串 i…j 中最长回文子序列的长度。 

3、状态方程

4、算法实现

package main

import "fmt"


func DP(str string, length int) int {
	byteSlice := []byte(str)

	// 创建备忘录
	dp := make([][]int, length)
	for i := range dp{
		dp[i] = make([]int, length)
	}

	// 初始化状态
	for i := 0; i < length; i++ {
		dp[i][i] = 1
	}

	// 转移方程转换实现
	for i := length - 1; i >= 0; i-- {
		for j := i+1; j < length; j++ {
			if byteSlice[i] == byteSlice[j] {
				dp[i][j] = 2 + dp[i+1][j-1];
			} else {
				if dp[i+1][j] > dp[i][j-1] {
					dp[i][j] = dp[i+1][j]
				} else {
					dp[i][j] = dp[i][j-1]
				}
			}
		}
	}
	return dp[0][length-1] // 输出答案
}

func main() {
	str := "asssasms"
	length := len(str)
	fmt.Println(DP(str, length))  // 输出答案
}

三、最长公共子序列

1、问题描述

问题:给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。若这两个字符串没有公共子序列,则返回 0。

其中:

1 ≤ text1.length ≤ 1000;

1 ≤ text2.length ≤ 1000;

输入的字符串只含有小写英文字符。 


示例1:

输入:text1 = "abcde", text2 = "ade" 
输出:3  
解释:最长公共子序列是 "ade",它的长度为 3。

2、算法分析

1)初始化状态

        当两个字符的其中一个为空串,或同时为空串时,原问题的答案肯定是 0。显然,一个字符串与空串的公共子序列肯定是空的。 

2)状态参数

        用变量 i 和变量 j 描述了整个问题的求解空间,备忘录是基于二维数组构建的。因此,我们的状态参数就是变量 i 和变量 j。 

3)决策

对于 text1 和 text2 这两个字符串中的每个字符 text1[i] 和 text2[j],其实只有两种选择:

1、text1[i−1]==text2[j−1],即当前遍历的两个字符在最长公共子序列中,此时 DP[i][j]=1+DP[i−1][j−1];

2、text1[i−1]!=text2[j−1],即当前遍历的两个字符至少有一个不在最长公共子序列中。仿照最长回文子序列的处理方法,由于两个字符至少有一个不在,因此我们需要丢弃一个。因此在不等的情况下,需要进一步作出决策。 

由于我们要求的是最长公共子序列,因此哪个子问题的答案比较长,就留下谁:max(DP[i−1][j], DP[i][j−1])。

4)备忘录

        DP[i][j] 表示的是 text1[0…i] 和 text2[0…j] 的最长公共子序列的长度。 

3、状态方程

4、算法实现

package main

import "fmt"


func DP(str1 string, str2 string) int {
	byteSlice1 := []byte(str1)
	byteSlice2 := []byte(str2)

	length1 := len(str1)
	length2 := len(str2)

	// 创建备忘录
	dp := make([][]int, length1+1)
	for i := range dp{
		dp[i] = make([]int, length2+1)
	}

	// 初始化状态
	for i := 0; i < length1+1; i++ {
		for j := 0; j  < length2+1; j++ {
			dp[i][j] = 0
		}
	}

	// 转移方程转换实现
	for i := 1; i<= length1; i++ {
		for j := 1; j <= length2; j++ {
			if byteSlice1[i-1] == byteSlice2[j-1] {
				dp[i][j] = 1 + dp[i-1][j-1];
			} else {
				if dp[i-1][j] > dp[i][j-1] {
					dp[i][j] = dp[i-1][j]
				} else {
					dp[i][j] = dp[i][j-1]
				}
			}
		}
	}
	return dp[length1][length2] // 输出答案
}

func main() {
	str1 := "abcde"
	str2 := "ade"
	fmt.Println(DP(str1, str2))  // 输出答案
}

声明:本文参考极客时间《动态规划面试宝典》 

相关文章:

  • python中namedtuple函数用法详解
  • C++设计模式---模板方法模式
  • 数据结构和算法——绪论
  • 最小生成树算法的相关变形题
  • Android中常用的几种容器视图的使用
  • 随手记面试录
  • VMware软件下载安装以及在VMware中安装Centos-stream
  • JCL入门教程
  • 5.6如何寻找最长回文子串
  • tkinter-event事件
  • Windows10环境gradle安装与配置
  • DELMIA弧焊虚拟仿真:带变位机的机器人弧焊焊接程序自动生成方法
  • Redis 非关系型数据库学习(三)---- Redis 基础知识
  • 离线数仓(2):数据仓库相关架构和规范
  • MySQL-数据类型和DDL
  • 【Linux系统编程】快速查找errno错误码信息
  • 【译】理解JavaScript:new 关键字
  • 07.Android之多媒体问题
  • Bytom交易说明(账户管理模式)
  • Git同步原始仓库到Fork仓库中
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • JS实现简单的MVC模式开发小游戏
  • js算法-归并排序(merge_sort)
  • laravel with 查询列表限制条数
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • Lucene解析 - 基本概念
  • Making An Indicator With Pure CSS
  • React中的“虫洞”——Context
  • SQLServer之索引简介
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 回流、重绘及其优化
  • 跨域
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 前端性能优化--懒加载和预加载
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 如何胜任知名企业的商业数据分析师?
  • 一个SAP顾问在美国的这些年
  • k8s使用glusterfs实现动态持久化存储
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • ###C语言程序设计-----C语言学习(3)#
  • (1)(1.13) SiK无线电高级配置(五)
  • (2)(2.10) LTM telemetry
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (五)关系数据库标准语言SQL
  • (一)SpringBoot3---尚硅谷总结
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)visual stdio 书签功能介绍
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • .[hudsonL@cock.li].mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET Core 中插件式开发实现
  • .NET学习教程二——.net基础定义+VS常用设置