【问题标题】:Print all the subarrays with unique K different elements打印具有唯一 K 个不同元素的所有子数组
【发布时间】:2021-11-29 05:25:21
【问题描述】:

我遇到了this解决方案,和this,使用了滑动窗口技术,int[] A = {1, 2, 1, 2, 3};K=2的方法是这样的:-

如上图所示,它得到了带有元素的子数组

[1, 2]
[1, 2, 1]
[2, 1]
[2, 1, 2]
[1, 2]
[2, 3]

但是我不明白如何使用元素 {1, 2, 1, 2} 获取子数组

因为,恰好由两个元素组成的子数组是:-

[1, 2]
[1, 2, 1]
[2, 1]
[2, 1, 2]
[1, 2]
[2, 3]
[1, 2, 1, 2]

这是我的解决方案

import java.util.*;

public class Main {
    public static void main(String[] args) {
        int[] A = {1, 2, 1, 2, 3};
        int K = 2;

        HashMap<Integer, Integer> map = new HashMap<>();
        ArrayList<Integer> list = new ArrayList<>();

        
        for(int i = 0;i<A.length; i++){
            map.put(A[i], map.getOrDefault(A[i], 0) + 1);
            list.add(A[i]);

            if(map.size() == K) System.out.println(list);

            while(map.get(list.get(0)) > 1 || map.size() > K){
                map.put(list.get(0), map.get(list.get(0)) - 1);
                if (map.get(list.get(0)) == 0) map.remove(list.get(0));
                
                list.remove(0);
              
                if(map.size() == K) System.out.println(list);
            }
        }
    }
}

给出输出

[1, 2]
[1, 2, 1]
[2, 1]
[2, 1, 2]
[1, 2]
[2, 3]

但我不明白如何在此方法中包含{1, 2, 1, 2}。 我哪里错了!

【问题讨论】:

    标签: java algorithm sub-array


    【解决方案1】:

    我注意到的第一件事是,您提到的两个问题都是关于查找具有 K 个唯一元素的子数组的 count,而不是 printing他们就像你在这里尝试做的那样。这是一个可能影响代码阅读和理解方式的差异,值得指出:)

    关于 [1, 2, 1, 2] 如何包含在结果中,我查看了您包含的 GeeksForGeeks 链接。我从中得到的要点是您的代码中似乎缺少的要点是 prefix 的想法。

    如您在上面发布的图片中所见,算法的主要逻辑会跟踪滑动窗口。由于该算法正在寻找不超过 K 个元素的子数组,因此它在循环的每次迭代结束时将滑动窗口的大小限制为 K。因此,需要有一种方法来跟踪元素重复的情况 - 否则,算法不会计算总元素超过 K 个的子数组,而是 K 个唯一元素的重复。

    这就是前缀的来源。正如您在上面发布的图片中看到的那样,该算法包括在滑动窗口每次增加到大于 K 的大小时检查其内容。

    如果窗口有超过 K 个元素,因为它包含重复元素,则第一个元素被分隔为“前缀”(如果已经存在,则添加到它)。这将窗口的大小限制为 K,同时还跟踪前缀仍然是子数组的有效部分。然后在窗口继续滑动时跟踪此前缀的大小。对于算法找到的每个新的有效子数组,它将有效子数组的总数增加 1(对于新的 K 长度子数组)加上前缀的长度。这是因为每个可以从前缀构造的子数组,当与当前滑动窗口组合时,仍然是一个由 K 个唯一元素组成的子数组。这就是算法中 [1, 2, 1, 2] 的计算方式——当 i = 5 时,“滑动窗口”为 [1, 2](输入列表中每个数字的第二次出现),前缀size 为 2 - 表示 [1, 2] 的列表(输入列表中每个数字的第一次出现)。因此,算法中此时有效子数组的总数为 3 - [1, 2](滑动窗口),[2, 1, 2](带有前缀最后一个元素的滑动窗口),以及[1, 2, 1, 2](滑动窗口前面加上了整个前缀)。

    如果窗口有超过 K 个元素仅仅是因为每个元素都是唯一的,那么算法就知道它到达了一个有效子数组的末尾——当前窗口和任何在它前面加上部分前缀的子数组都会总是有超过 K 个独特的元素。此时,算法会重置前缀,将窗口缩小到 K 个元素,然后继续处理。

    【讨论】:

      【解决方案2】:

      这是一种线性方法。

      使用两个索引,一个用于计算索引之间不同元素数量的计数器,以及一个计数映射(从元素到索引之间的计数)。

      When the number of distinct elements is <= your target:
      1) print if you have equality
      2) increment the right index
      3) update the counting map
      4) increment the number of distinct elements if step 3 took something from zero or uninitialized to 1.
      
      When the number of distinct elements is > your target:
      1) increment the left index
      2) update the counting map
      3) decrement the number of distinct elements of step 2 to something from 1 to zero.
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-01
        • 2015-06-28
        • 1970-01-01
        • 1970-01-01
        • 2013-02-13
        • 1970-01-01
        • 1970-01-01
        • 2017-08-22
        相关资源
        最近更新 更多