718.最长重复子数组

102 阅读1分钟

题目:
给两个整数数组 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