与数组具有相同“度”的子数组的数量

时间:2017-08-11 17:31:52

标签: arrays algorithm

因此在测验中询问了这个问题,问题就像:

您将获得一个数组'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

2 个答案:

答案 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;
        }

}