1.最初上升子序列
func lengthOfLIS(nums []int) int {
length := len(nums)
dp := make([]int, length)
for i:=0;i<length;i++{
dp[i] = 1
}
//对于每一个i,我们都需要回过头去遍历是否可以更新长度
for i:=0;i<length;i++{
for j:=0;j<i;j++{
if nums[i]>nums[j]{
dp[i] = max(dp[i],dp[j]+1)
}
}
}
maxLen := 0
for i:=0;i<length;i++{
if maxLen<dp[i]{
maxLen = dp[i]
}
}
return maxLen
}
2.最长连续递增序列
func findLengthOfLCIS(nums []int) int {
length := len(nums)
// 初始化
dp := make([]int,length)
for i:=0;i<length;i++{
dp[i] = 1
}
// 递推
for i:=1;i<length;i++{
if nums[i]>nums[i-1]{
dp[i] = dp[i-1]+1
}
}
// 查找最大值
maxLen := 0
for i:=0;i<length;i++{
if maxLen<dp[i]{
maxLen = dp[i]
}
}
return maxLen
}
3.最长重复子数组
这道题目的初始化比较有趣,需要进行一定的注意。
func findLength(nums1 []int, nums2 []int) int {
len1 := len(nums1)
len2 := len(nums2)
dp := make([][]int, len1)
for i := 0; i < len1; i++ {
dp[i] = make([]int, len2)
}
maxLen := 0
// 初始化
for i := 0; i < len2; i++ {
if nums1[0] == nums2[i] {
dp[0][i] = 1
}
if dp[0][i] > maxLen {
maxLen = dp[0][i]
}
}
for i := 0; i < len1; i++ {
if nums2[0] == nums1[i] {
dp[i][0] = 1
}
if dp[i][0] > maxLen {
maxLen = dp[i][0]
}
}
//递推
for i := 1; i < len1; i++ {
for j := 1; j < len2; j++ {
if nums1[i] == nums2[j] {
dp[i][j] = max(dp[i][j], dp[i-1][j-1]+1)
if dp[i][j] > maxLen {
maxLen = dp[i][j]
}
}
}
}
return maxLen
}
4.最长公共子序列
func longestCommonSubsequence(text1 string, text2 string) int {
len1 := len(text1)
len2 := len(text2)
dp := make([][]int,len1+1)
for i:=0;i<=len1;i++{
dp[i] = make([]int,len2+1)
}
//初始化
//开始递归
for i:=1;i<=len1;i++{
for j:=1;j<=len2;j++{
if text1[i-1]==text2[j-1]{
dp[i][j] = max(dp[i][j],dp[i-1][j-1]+1)
}else{
dp[i][j] = max(dp[i-1][j],dp[i][j-1])
}
}
}
return dp[len1][len2]
}
5.不相交的线
实际上与上题”最长公共子序列“完全相同
func maxUncrossedLines(nums1 []int, nums2 []int) int {
len1 := len(nums1)
len2 := len(nums2)
dp := make([][]int,len1+1)
for i:=0;i<=len1;i++{
dp[i] = make([]int,len2+1)
}
for i:=1;i<=len1;i++{
for j:=1;j<=len2;j++{
if nums1[i-1]==nums2[j-1]{
dp[i][j] = max(dp[i][j],dp[i-1][j-1]+1)
}else{
dp[i][j] = max(dp[i-1][j],dp[i][j-1])
}
}
}
return dp[len1][len2]
}
6.最大子序和
6.1 贪心
func maxSubArray(nums []int) int {
max := nums[0]
count := 0
for i := 0; i < len(nums); i++{
count += nums[i]
if count > max{
max = count
}
if count < 0 {
count = 0
}
}
return max
}
6.2 动态规划
func maxSubArray(nums []int) int {
//创建dp数组
//dp数组中i的含义为以nums[i]结尾的最大连续子数组和
dp := make([]int,len(nums))
//dp数组初始化
dp[0]=nums[0]
//递推
for i:=1;i<len(nums);i++{
dp[i] = max(dp[i-1]+nums[i],nums[i])
}
//寻找最大
ans := dp[0]
for i:=0;i<len(nums);i++{
if dp[i]>ans{
ans = dp[i]
}
}
return ans
}
7.判断子序列
7.1 非动态规划
func isSubsequence(s string, t string) bool {
if len(s)==0 {
return true
}
if len(s)>len(t){
return false
}
index := 0
for i:=0;i<len(t);i++{
if s[index]==t[i]{
index++
if index==len(s){
return true
}
}
}
return false
}
7.2 动态规划
func isSubsequence(s string, t string) bool {
if len(s)==0 {
return true
}
if len(s)>len(t){
return false
}
len1 := len(s)
len2 := len(t)
dp := make([][]int,len1+1)
for i:=0;i<=len1;i++{
dp[i] = make([]int,len2+1)
}
for i:=1;i<=len1;i++{
for j:=1;j<=len2;j++{
if s[i-1]==t[j-1]{
dp[i][j] = dp[i-1][j-1]+1
}else{
dp[i][j] = dp[i][j-1]
}
}
}
return dp[len1][len2]==len1
}
8.不同的子序列
func numDistinct(s string, t string) int {
dp:= make([][]int,len(s)+1)
//dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。
for i:=0;i<len(dp);i++{
dp[i] = make([]int,len(t)+1)
}
// 初始化
for i:=0;i<len(dp);i++{
//[i][0]即空字符出现的个数,只能全部删除,所以都为1
dp[i][0] = 1
}
// dp[0][j] 为 0,默认值,因此不需要初始化
for i:=1;i<len(dp);i++{
for j:=1;j<len(dp[i]);j++{
if s[i-1] == t[j-1]{
dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
}else{
dp[i][j] = dp[i-1][j]
}
}
}
return dp[len(dp)-1][len(dp[0])-1]
}
9.两个字符串的删除操作
func minDistance(word1 string, word2 string) int {
//dp[i][j]表示word1[:i-1]和word[:j-1]中相同的子序列长度
dp := make([][]int,len(word1)+1)
for i:=0;i<=len(word1);i++{
dp[i] = make([]int,len(word2)+1)
}
//初始化
for i:=0;i<=len(word1);i++{
dp[i][0] = i
}
for j:=0;j<=len(word2);j++{
dp[0][j] = j
}
//递推
for i:=1;i<=len(word1);i++{
for j:=1;j<=len(word2);j++{
if word1[i-1]==word2[j-1]{
dp[i][j] = dp[i-1][j-1]
}else{
dp[i][j] = min(dp[i-1][j-1]+2,dp[i-1][j]+1,dp[i][j-1]+1)
}
}
}
return dp[len(word1)][len(word2)]
}
10.编辑距离
func minDistance(word1 string, word2 string) int {
//dp[i][j]代表以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]
dp := make([][]int, len(word1)+1)
for i:=0;i<=len(word1);i++{
dp[i] = make([]int,len(word2)+1)
}
//dp数组初始化
for i:=0;i<=len(word1);i++{
dp[i][0] = i
}
for j:=0;j<=len(word2);j++{
dp[0][j] = j
}
//dp数组推导
for i:=1;i<=len(word1);i++{
for j:=1;j<=len(word2);j++{
if word1[i-1]==word2[j-1]{
dp[i][j] = dp[i-1][j-1]
}else{
dp[i][j] = min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1
}
}
}
return dp[len(word1)][len(word2)]
}
11.回文子串
func countSubstrings(s string) int {
//dp创建
dp := make([][]bool,len(s))
for i:=0;i<len(s);i++{
dp[i]=make([]bool,len(s))
}
result := 0
//递推
for i:=len(s)-1;i>=0;i--{
for j:=i;j<len(s);j++{
if s[i]==s[j]{
if j-i<=1{
result += 1
dp[i][j]=true
}else if dp[i+1][j-1]{
result += 1
dp[i][j]=true
}
}
}
}
return result
}
12.最长回文子序列
func longestPalindromeSubseq(s string) int {
//创建dp数组,dp[i][j]表示[i:j]中最长的回文子序列的长度
dp := make([][]int,len(s))
for i:=0;i<len(s);i++{
dp[i] = make([]int,len(s))
dp[i][i] = 1
}
//dp数组递推
for i:=len(s)-1;i>=0;i--{
for j:=i+1;j<len(s);j++{
if s[i] == s[j] {
dp[i][j] = dp[i+1][j-1] + 2
} else {
dp[i][j] = max(dp[i][j-1], dp[i+1][j])
}
}
}
return dp[0][len(s)-1]
}