关于组合去重问题的解决办法

1 我们经常会遇到这样一种情况, 我们的目的是收集若干个符合条件的元素的组合, 但是由于元素有可能会重复, 所以, 我们收集到的组合也有很大的可能会重复. 但是我们要求获得的组合不能允许有重复, 这就要牵扯到去重的操作

 

2 对于去重, 我们的第一想法就是, 先把所有可能的情况进行收集, 然后再在所有的情况之中进行去重操作, 想法固然正确, 但是如果遇到及其大量的数据的话, 一方面, 我们进行收集元素的过程会耗费大量的时间和内存, 另一方面, 我们去重的时候又需要对所有的元素进行重新遍历和去重操作, 又会耗费大量的时间的内存, 综合考虑一下, 这种做法是很不可取的.

 

3 所以, 我们可以考虑在收集元素的过程中就进行去重操作, 具体做法和思想如下:

  

  (1) 只进行一层遍历的操作时, 这种情况比较简单, 我们只需要在遍历元素的时候, 遇到相同的元素就直接跳过不进行操作即可, 这是之前学到的一个小技巧,代码如下:

    

1 for(int i = 0; i < 原数组.length; i++){
2 
3     if(i != 0 && 原数组[i] == 原数组[i-1]){
4 
5           continue; 
6     }          
7 }    

  (2) 如果是需要进行多次遍历操作(往往不知道需要遍历多少层)时, 一般想回溯和递归中会经常遇到, 那么, 下面这个技巧就比较厉害了

 

    我们都知道, 回溯和递归都可以抽象成一个N叉树模型, 横向进行遍历, 纵向进行递归, 也就是说, 横向是同层, 纵向是同树枝

    我们在收集元素时进行去重操作时, 就需要对收集的每一个小元素进行去重操作, 一般分为3中情况:

    1 同层元素不重复

    2 同树枝元素不重复

    3 同层元素和同树枝元素都不重复

  这里需要用到的一个技巧就是, 我们可以维护一个map, 用来记录一个元素是否使用过, 在进行每一次元素添加的时候, 先查看map中是否有此元素的使用记录, 然后根据使用记录情况, 来对这个元素进行相应的操作(不操作也算是一种操作)

  如果是需要同层元素不重复, 那么就需要在每一层遍历维护一个map, 每一次递归时都传入一个新的map

  如果是需要同树枝元素不重复, 那么我们就需要在所有的递归操作时共用一个map, 但是这个东西就需要对这个map进行回溯, 否则就会造成不同树枝也不能拥有相同元素的情况

  如果是同层元素和同树枝元素都不重复的情况, 我们就需要维护两个map, 一个用于每一层的遍历(仍然是需要每一个都传入一个新的map), 一个是用于递归操作(所有递归操作共用一个map, 也需要进行回溯map), 相当于是同时运用这两条规则.

 

 

重点盲点缺点:

  对于上述总结, 我发现自己走进了一个极大的误区, 那就是, 上面所有的总结可能适用于   大多数-需要排好序    的数组中抽取部分数, 

  但是, 我忽略了一点, 那就是, 去重的逻辑不仅仅是上面几种情况, 不同的题目会有不同的需求, 去重的思路也可能后不一样, 例如, LeetCode题目491,  其去重逻辑就不需要num[i] == nums[i-1], 而只是需要map.get(i) != null;

  所以, 即使我们有模板, 即使我们有套路, 但是, 我们仍然需要具体问题具体分析, 不可被套路困住

posted @ 2021-03-16 09:55  0龙行者0  阅读(363)  评论(0编辑  收藏  举报