最长重复子数组
难度:
标签:
题目描述
代码结果
运行时间: 59 ms, 内存: 16.2 MB
/*
* 思路:
* 使用Java Stream API虽然不如使用动态规划来得直接,但可以先构造DP数组,再使用Stream操作来找到最大值。
*/
import java.util.Arrays;
import java.util.stream.IntStream;
public class Solution {
public int findLength(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (nums1[i - 1] == nums2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
}
}
}
return Arrays.stream(dp).flatMapToInt(IntStream::of).max().orElse(0);
}
}
解释
方法:
这个题解使用了二分查找和滚动哈希的思路。首先定义了一个 check 函数,用于判断是否存在长度为 length 的公共子数组。check 函数中,分别计算 nums1 和 nums2 的长度为 length 的子数组的哈希值,并使用滚动哈希的方法快速计算出所有可能的子数组哈希值,然后判断是否存在相同的哈希值,如果存在则说明存在长度为 length 的公共子数组。接下来使用二分查找的方法,初始化 left 为 0,right 为 min(len(nums1), len(nums2)),然后进行二分查找,如果 check(mid) 为 True,说明存在长度为 mid 的公共子数组,则将 ans 更新为 mid,并将 left 更新为 mid + 1,否则将 right 更新为 mid - 1。最终返回 ans 即为最长重复子数组的长度。
时间复杂度:
O((n + m) * log(min(n, m)))
空间复杂度:
O(n)
代码细节讲解
🦆
哈希冲突在滚动哈希中是如何被处理的?在本题解中是否有额外的机制来处理可能的哈希碰撞?
▷🦆
您使用的 `base` 和 `mod` 值是如何选取的?这些值对哈希的效率和准确性有何影响?
▷🦆
为什么选择二分查找来确定最长的公共子数组长度?直接使用动态规划或其他方法是否可行?
▷🦆
在二分查找过程中,如果`check(mid)`函数返回True,为什么选择将`left`更新为`mid + 1`而不是`mid`?
▷相关问题
长度最小的子数组
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3]
是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4] 输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1] 输出:0
提示:
1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105
进阶:
- 如果你已经实现
O(n)
时间复杂度的解法, 请尝试设计一个O(n log(n))
时间复杂度的解法。