文章目录
q5 最长回文子串
题目传送门
题解
首先要把动态转移方程给找出来,可以发现dp[i][j]如果是回文串,那么dp[i + 1][j - 1]得是回文串,其中dp[i][j]表示字符串下标i到j的子串。同时还要考虑边界条件,那就是如果子串长度小于2,那么就一定是回文串,如果子串长度等于2,那么是回文串就只需要满足dp[i] == d[j]。
func longestPalindrome(s string) string {
n := len(s)
dp := make([][]bool, n)
for i, _ := range dp {
dp[i] = make([]bool, n)
}
ans := ""
// 第一层遍历子串的长度
for l := 0; l < n; l++ {
// 第二层是子串的左边界
for i := 0; i + l < n; i++ {
// j是子串的右边界
j := i + l
if l == 0 {
dp[i][j] = true
} else if l == 1 {
dp[i][j] = (s[i] == s[j])
} else {
dp[i][j] = (s[i] == s[j] && dp[i + 1][j - 1])
}
// 更新最大值
if dp[i][j] && l + 1 > len(ans) {
ans = s[i:j + 1]
}
}
}
return ans
}
q53 最大子数组和
题目传送门
题解
遍历数组,开辟一个新数组dp,循环遍历nums,让dp[i] = nums[i],然后判断dp[i] + dp[i - 1]是否大于dp[i],如果大于就让dp[i] += dp[i - 1]
func maxSubArray(nums []int) int {
dp := make([]int, len(nums))
dp[0] = nums[0]
maxSum := nums[0]
for i := 1; i < len(nums); i++ {
dp[i] = nums[i]
if dp[i - 1] + dp[i] > dp[i] {
dp[i] += dp[i - 1]
}
if dp[i] > maxSum {
maxSum = dp[i]
}
}
return maxSum
}
q62 不同路径
题目传送门
题解
这道题目的动态转移方程非常简单,因为只能向下和向右走,所以dp[i][j] = dp[i - 1][j] + dp[i][j - 1],最后处理一下边界条件即可,dp[i][0]和dp[0][j]都等于1,因为都只有一条路径通往边界。
func uniquePaths(m int, n int) int {
dp := make([][]int, m)
for i := 0; i < m; i++ {
dp[i] = make([]int, n)
dp[i][0] = 1
}
for j := 0; j < n; j++ {
dp[0][j] = 1
}
for i := 1; i < m; i++ {
for j := 1; j < n; j++ {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
}
}
return dp[m - 1][n - 1]
}
q64 最小路径和
题目传送门
题解
这道题使用动态规划求解,动态转移方程是dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]),然后处理一下边界情况即可,边界是当i == 0或者j == 0的时候,这个时候dp[i][0] = dp[i - 1][0],dp[0][j] = dp[0][j - 1]。
func minPathSum(grid [][]int) int {
m, n := len(grid), len(grid[0])
dp := make([][]int, m)
dp[0] = make([]int, n)
dp[0][0] = grid[0][0]
for i := 1; i < m; i++ {
dp[i] = make([]int, n)
dp[i][0] = grid[i][0]
dp[i][0] += dp[i - 1][0]
}
for j := 1; j < n; j++ {
dp[0][j] = grid[0][j]
dp[0][j] += dp[0][j - 1]
}
for i := 1; i < m; i++ {
for j := 1; j < n; j++ {
dp[i][j] = grid[i][j]
dp[i][j] += min(dp[i - 1][j], dp[i][j - 1])
}
}
return dp[m - 1][n - 1]
}
func min(a, b int) int {
if a < b {
return a
} else {
return b
}
}
q70 爬楼梯
题目传送门
题解
这道题使用递推来求解即可,递推公式是step[i] = step[i - 1] + step[i - 2],然后处理一下边界条件即可,当i == 1时,step[1] = 1,当i == 2时,step[2] = 2。
func climbStairs(n int) int {
if n <= 2 {
return n
}
step1, step2, step3 := 1, 2, 0
for i := 3; i <= n; i++ {
step3 = step1 + step2
step1 = step2
step2 = step3
}
return step3
}
q118 杨辉三角
题目传送门
题解
这道题使用动态规划求解,状态转移方程是dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j],然后处理一下边界条件即可,如果行数小于3,那么所有元素都是1,当行数大于等于3时,只有当列数不是第一个和最后一个时才满足状态转移方程,否则都为1 。
func generate(numRows int) [][]int {
res := [][]int{{1}}
if numRows == 1 {
return res
}
res = append(res, []int{1, 1})
if numRows == 2 {
return res
}
for i := 3; i <= numRows; i++ {
var rows []int
for j := 1; j <= i; j++ {
if j != 1 && j != i {
rows = append(rows, res[i - 2][j - 2] + res[i - 2][j - 1])
} else {
rows = append(rows, 1)
}
}
res = append(res, rows)
}
return res
}
q300 最长上升子序列
题目传送门
题解
首先定义一个数组dp用来保存到当前元素位置为止的最长上升子序列长度。要使用两层循环,第一层循环遍历nums数组,第二层循环遍历从零开始到nums数组当前元素的前一个元素,如果当前元素满足nums[i] > num[j] && dp[j] + 1 > dp[i],就执行dp[i] = dp[j] + 1来更新最长上升子序列。
func lengthOfLIS(nums []int) int {
dp := make([]int, len(nums))
maxLen := 0
for i := 0; i < len(nums); i++ {
dp[i] = 1
for j := 0; j < i; j++ {
if nums[i] > nums[j] && dp[j] + 1 > dp[i] {
dp[i] = dp[j] + 1
}
}
if dp[i] > maxLen {
maxLen = dp[i]
}
}
return maxLen
}
q1143 最长公共子序列
题目传送门
题解
定义一个数组dp[i][j]表示text1[1…i]和text2[1…j]的最长公共子序列的长度,那么最终答案就是dp[len1][len2]。
这道题可以分为三种情况来考虑:
- text1[i]不在公共子序列中,那么dp[i][j] = dp[i - 1][j]
- text2[j]不在公共子序列中,那么dp[i][j] = dp[i][j - 1]
- text1[i] == text2[j],这个时候dp[i][j] = dp[i - 1][j - 1] + 1
dp[i][j]取上述三种情况的最大值。然后处理一下边界条件,dp[i][0]和dp[0][j]都为0 。
func longestCommonSubsequence(text1 string, text2 string) int {
len1, len2 := len(text1), 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++ {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
if text1[i - 1] == text2[j - 1] {
dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1)
}
}
}
return dp[len1][len2]
}
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}