因此在测验中询问了这个问题,问题就像:
您将获得一个数组'a',其元素范围为1-10 6 ,并且数组的大小可以最大为10 5 现在我们被要求找到与原始数组具有相同“度”的子数组的数量。数组的度数定义为数组中最大出现元素的频率。多个元素可以具有相同的频率。
我被困在这个问题上一个小时但却想不到任何解决方案。我该如何解决?
first-input
1,2,2,3,1
first-output 2
second-input
1,1,2,1,2,2
second-output 4
答案 0 :(得分:0)
最常出现的元素称为模式;此问题将度定义为频率计数。你的任务是:
识别所有模式值。 对于每个模式值,找到该值的索引范围。例如,在数组中
[1, 1, 2, 1, 3, 3, 2, 4, 2, 4, 5, 5, 5]
你有三种模式(1 2 5),度数为3.索引范围是
1 - 0:3
2 - 2:8
5 - 10:12
您需要计算包含这三个范围中至少一个的所有索引范围(子数组)。
我已经为这个例子量身打造了两个基本案例:重叠的模式和不重叠的模式。请注意,包含是一个没有实际意义的点:如果您有一个阵列,其中一个模式的范围包含另一个:
[0,1,1,1,0,0]
您可以完全忽略外部的:包含0
的任何子数组也包含1
。
分析
子数组由两个数字定义,即起始和结束索引。因为我们必须有0< = start< = end< = len(数组),这就是"握手"数组边界之间的问题。我们有N(N + 1)/ 2个可能的子阵列。
对于10 ** 5个元素,你可以从这里强制解决问题:对于每对索引,检查该范围是否包含任何模式范围。但是,你可以通过区间识别轻松地将其降低。
算法
从左到右逐步调整模式范围。首先,计算包含第一个模式范围[0:3]的所有子范围。只有1个可能的开始[0]和10个可能的结束[3:12];那个10个子阵列。
现在转到第二个模式范围,[2:8]。您需要计算包含此内容的子数组,但排除您已经计算过的数据。由于存在重叠,因此需要一个晚于0的起点,或一个3之前的结束点。对于给定的范围,这个第二个子句是不可能的。
因此,你考虑开始[1:2],结束[8:12]。这是2 * 5个更多的子阵列。
对于第三个范围[10:12(无重叠),您需要一个不包含任何其他子范围的起点。这意味着任何起点[3:10]都可以。由于只有一个可能的端点,因此您有8 * 1或8个子阵列。
你能把它变成正式的吗?
答案 1 :(得分:0)
参考leet代码 https://leetcode.com/problems/degree-of-an-array/solution/ 解决
class Solution {
public int findShortestSubArray(int[] nums) {
Map<Integer, Integer> left = new HashMap(),
right = new HashMap(), count = new HashMap();
for (int i = 0; i < nums.length; i++) {
int x = nums[i];
if (left.get(x) == null) left.put(x, i);
right.put(x, i);
count.put(x, count.getOrDefault(x, 0) + 1);
}
int ans = nums.length;
int degree = Collections.max(count.values());
for (int x: count.keySet()) {
if (count.get(x) == degree) {
ans = Math.min(ans, right.get(x) - left.get(x) + 1);
}
}
return ans;
}
}