题目:
给两个整数数组 nums1 和 nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度 。
算法:
方法一:暴力
这种解法会超时,但是我们可以在此基础上进行复杂度优化。
一般的思路也是如此,先实现走通思路,再优化。
func findLength(nums1 []int, nums2 []int) int {
ans := 0
for i := range nums1 {
k := i
for j := range nums2 {
if k == len(nums1) || nums1[k] != nums2[j] {
break
}
k ++
}
if k - i > ans {
ans = k - i
}
}
return ans
}
方法二:动态规划
从后边往前边规划
func findLength(nums1 []int, nums2 []int) int {
ans := 0
dp := make([][]int, len(nums1))
for i := range dp {
dp[i] = make([]int, len(nums2))
}
for i := len(nums1) - 1; i >=0; i -- {
for j := len(nums2) - 1; j >= 0; j -- {
if nums1[i] == nums2[j] {
if i + 1 < len(nums1) && j + 1 < len(nums2) {
dp[i][j] = dp[i + 1][j + 1] + 1
} else {
dp[i][j] = 1
}
} else {
dp[i][j] = 0
}
if dp[i][j] > ans {
ans = dp[i][j]
}
}
}
return ans
}
方法三:动态规划二
从前面往后边规划,时间复杂度O(m*n)
func findLength(nums1 []int, nums2 []int) int {
ans := 0
dp := make([][]int, len(nums1))
for i := range dp {
dp[i] = make([]int, len(nums2))
}
for i := 0; i< len(nums1); i ++ {
for j := 0; j < len(nums2); j ++ {
if nums1[i] == nums2[j] {
if i - 1 >= 0 && j - 1 >= 0 {
dp[i][j] = dp[i - 1][j - 1] + 1
} else {
dp[i][j] = 1
}
} else {
dp[i][j] = 0
}
if dp[i][j] > ans {
ans = dp[i][j]
}
}
}
return ans
}
方法三:滑动窗口
将nums1和nums2滑动,这样只用比较从头到尾,时间复杂度O(n+m)*min(n,m)
func findLength(nums1 []int, nums2 []int) int {
ans := 0
n := len(nums1)
m := len(nums2)
for i := 0; i < n; i ++ {
length := min(m, n - i)
ret := doFind(nums1, nums2, i, 0, length)
if ret > ans {
ans = ret
}
}
for j := 0; j < n; j ++ {
length := min(m - j, n)
ret := doFind(nums1, nums2, 0, j, length)
if ret > ans {
ans = ret
}
}
return ans
}
func doFind(nums1 []int, nums2 []int, add1, add2, length int) int {
ans := 0
k := 0
for i := 0; i < length; i ++ {
if nums1[i + add1] == nums2[i + add2] {
k ++
} else {
k = 0
}
if k > ans {
ans = k
}
}
return ans
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
方法四:二分+hash