规范格式

This commit is contained in:
YDZ
2020-08-07 15:50:06 +08:00
parent 854a339abc
commit 4e11f4028a
1438 changed files with 907 additions and 924 deletions

View File

@ -0,0 +1,86 @@
package leetcode
const primeRK = 16777619
// 解法一 二分搜索 + Rabin-Karp
func findLength(A []int, B []int) int {
low, high := 0, min(len(A), len(B))
for low < high {
mid := (low + high + 1) >> 1
if hasRepeated(A, B, mid) {
low = mid
} else {
high = mid - 1
}
}
return low
}
func min(a int, b int) int {
if a > b {
return b
}
return a
}
func hashSlice(arr []int, length int) []int {
// hash 数组里面记录 arr 比 length 长出去部分的 hash 值
hash, pl, h := make([]int, len(arr)-length+1), 1, 0
for i := 0; i < length-1; i++ {
pl *= primeRK
}
for i, v := range arr {
h = h*primeRK + v
if i >= length-1 {
hash[i-length+1] = h
h -= pl * arr[i-length+1]
}
}
return hash
}
func hasSamePrefix(A, B []int, length int) bool {
for i := 0; i < length; i++ {
if A[i] != B[i] {
return false
}
}
return true
}
func hasRepeated(A, B []int, length int) bool {
hs := hashSlice(A, length)
hashToOffset := make(map[int][]int, len(hs))
for i, h := range hs {
hashToOffset[h] = append(hashToOffset[h], i)
}
for i, h := range hashSlice(B, length) {
if offsets, ok := hashToOffset[h]; ok {
for _, offset := range offsets {
if hasSamePrefix(A[offset:], B[i:], length) {
return true
}
}
}
}
return false
}
// 解法二 DP 动态规划
func findLength1(A []int, B []int) int {
res, dp := 0, make([][]int, len(A)+1)
for i := range dp {
dp[i] = make([]int, len(B)+1)
}
for i := len(A) - 1; i >= 0; i-- {
for j := len(B) - 1; j >= 0; j-- {
if A[i] == B[j] {
dp[i][j] = dp[i+1][j+1] + 1
if dp[i][j] > res {
res = dp[i][j]
}
}
}
}
return res
}

View File

@ -0,0 +1,58 @@
package leetcode
import (
"fmt"
"testing"
)
type question718 struct {
para718
ans718
}
// para 是参数
// one 代表第一个参数
type para718 struct {
A []int
B []int
}
// ans 是答案
// one 代表第一个答案
type ans718 struct {
one int
}
func Test_Problem718(t *testing.T) {
qs := []question718{
question718{
para718{[]int{0, 0, 0, 0, 0}, []int{0, 0, 0, 0, 0}},
ans718{5},
},
question718{
para718{[]int{1, 2, 3, 2, 1}, []int{3, 2, 1, 4, 7}},
ans718{3},
},
question718{
para718{[]int{0, 0, 0, 0, 1}, []int{1, 0, 0, 0, 0}},
ans718{4},
},
question718{
para718{[]int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}},
ans718{59},
},
}
fmt.Printf("------------------------Leetcode Problem 718------------------------\n")
for _, q := range qs {
_, p := q.ans718, q.para718
fmt.Printf("【input】:%v 【output】:%v\n", p, findLength(p.A, p.B))
}
fmt.Printf("\n\n\n")
}

View File

@ -0,0 +1,37 @@
# [718. Maximum Length of Repeated Subarray](https://leetcode.com/problems/maximum-length-of-repeated-subarray/)
## 题目:
Given two integer arrays `A` and `B`, return the maximum length of an subarray that appears in both arrays.
**Example 1:**
Input:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
Output: 3
Explanation:
The repeated subarray with maximum length is [3, 2, 1].
**Note:**
1. 1 <= len(A), len(B) <= 1000
2. 0 <= A[i], B[i] < 100
## 题目大意
给两个整数数组 A B 返回两个数组中公共的长度最长的子数组的长度
## 解题思路
- 给出两个数组求这两个数组中最长相同子串的长度
- 这一题最容易想到的是 DP 动态规划的解法`dp[i][j]` 代表在 A 数组中以 `i` 下标开始的子串与 B 数组中以 `j` 下标开始的子串最长相同子串的长度状态转移方程为 `dp[i][j] = dp[i+1][j+1] + 1` ( `A[i] == B[j]`)。这种解法的时间复杂度是 O(n^2)空间复杂度 O(n^2)。
- 这一题最佳解法是二分搜索 + `Rabin-Karp`比较相同子串耗时的地方在于需要一层循环遍历子串所有字符但是如果比较两个数字就很快`O(1)` 的时间复杂度所以有人就想到了能不能把字符串也映射成数字呢这样比较起来就非常快这个算法就是 `Rabin-Karp` 算法字符串映射成一个数字不能随意映射还要求能根据字符串前缀动态增加比较下一个字符串的时候可以利用已比较过的前缀加速之后的字符串比较 Rabin-Karp 算法中有一个码点的概念类似于10进制中的进制具体的算法讲解可以见这篇
[基础知识 - Rabin-Karp 算法](https://www.cnblogs.com/golove/p/3234673.html)
码点一般取值为一个素数 go `strings` 包里面取值是 16777619所以这一题也可以直接取这个值由于这一次要求我们找最长长度所以把最长长度作为二分搜索的目标先将数组 A 和数组 B 中的数字都按照二分出来的长度进行 `Rabin-Karp` hash A 中的 hash 与下标做映射关系存到 map 方便后面快速查找然后遍历 B 中的 hash hash 一致的时候再匹配下标如果下标存在且拥有相同的前缀那么就算找到了相同的子串了最后就是不断的二分找到最长的结果即可这个解法的时间复杂度 O(n * log n)空间复杂度 O(n)。