将具有重复元素的Array分区为具有唯一元素的数组

时间:2015-01-26 06:27:46

标签: java arrays unique duplicate-removal

我有一个结构如下的数组:

String Array = {"1","2","3","41","56","41","72","72","72","78","99"}

我希望将这个数组分成多个数组,这些数组的值不重复......就像这样:

String Array1 = {"1","2","3","41","56","72","78","99"}
String Array2 = {"41","72"}
String Array3 = {"72"}

有没有直接的方法在Java中执行此操作,或者我必须使用丑陋的循环执行此操作(开玩笑!)?

谢谢!

  

更新

我会让问题变得更难......现在我有一张地图,结构如下:

Map<String,String> map = new HashMap(){{
    put("1@@96","10");
    put("2@@100","5");
    put("3@@23","100");
    put("41@@34","14");
    put("56@@22","25");
    put("41@@12","100");
    put("72@@10","100");
    put("72@@100","120");
    put("72@@21","0");
    put("78@@22","7");
}}

请注意,这些值并不重要但是键很重要...... 我该怎么做才能将这个地图划分为子图,如:

Map map1 = {"1@@96" => "10"
            "2@@100" => "5"
            "3@@23" => "100"
            "41@@34" => "14"
            "56@@22" => "25"
            "72@@10" => "100"
            "78@@22" => "7"
            }

Map map2 = {
            "41@@12" => "100"
            "72@@100" => "120"
            }

Map map3 = {
            "72@@100" => "120"
            }

在地图的第一部分之前(在&#39; @@&#39;之前)是我希望唯一性基于的ID ...这就像数组示例但更难一点更复杂......

很抱歉中途改变了问题...

2 个答案:

答案 0 :(得分:2)

libs中可能没什么(似乎不够通用)但是有些想法:

O(n)时间和O(n)空间复杂度。在这里,您只需计算每个数字出现的次数,然后将它们放入多个结果数组中。

@Edit:正如@mpkorstanje指出的那样,如果你将数字输入更改为字符串或在最糟糕的情况下任何其他对象,这将降级为O(n ^ 2)。但在这种情况下,你应该修改你正在工作的数据的哈希imho,因为它没有很好地分发。

   public List<List<Integer>> split(int[] input) {
      Map<Integer, Integer> occurrences = new HashMap<>();
      int maxOcc = 0;
      for (int val : input) {
         int occ = 0;
         if (occurrences.containsKey(val)) {
            occ = occurrences.get(val);
         }
         if (occ + 1 > maxOcc) {
            maxOcc = occ + 1;
         }
         occurrences.put(val, occ + 1);
      }
      List<List<Integer>> result = new ArrayList<>(maxOcc);
      for (int i = 0; i < maxOcc; i++) {
         result.add(new LinkedList<>());
      }
      for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
         for (int i = 0; i < entry.getValue(); i++) {
            result.get(i).add(entry.getKey());
         }
      }
      return result;
   }

O(nlogn)时间和O(1)空间复杂度(不计算结果数组)但不保留顺序并“破坏”输入数组。在这里,您可以利用数组已经排序的事实,这样您就可以查看它并继续将元素添加到适当的结果列表中,具体取决于您是在查看重复条目还是“新”条目。

   public List<List<Integer>> split(int[] input) {
      Arrays.sort(input);
      int maxDup = getMaxDuplicateNumber(input);
      List<List<Integer>> result = new ArrayList<>(maxDup);
      for(int i = 0; i < maxDup; i++) {
         result.add(new LinkedList<>());
      }
      int count = 0;
      result.get(0).add(input[0]);
      for(int i = 1; i < input.length; i++) {
         if(input[i] == input[i-1]) {
            count++;
         } else {
            count = 0;
         }
         result.get(count).add(input[i]);
      }
      return result;
   }

   private int getMaxDuplicateNumber(int[] input) {
      int maxDups = 1;
      int currentDupCount = 1;
      for(int i = 1; i < input.length; i++) {
         if(input[i] == input[i - 1]) {
            currentDupCount++;
         } else {
            currentDupCount = 1;
         }
         if(currentDupCount > maxDups) {
            maxDups = currentDupCount;
         }
      }
      return maxDups;
   }

答案 1 :(得分:1)

如果没有循环,你就无法做到这一点。但是您可以使用一组来删除一些循环。您可以根据自己的喜好添加数据结构陷阱。

我假设这里的元素顺序必须与输入数组中元素的顺序一致。如果不是这样可以更有效地完成。

public static void main(String[] args) {
    String[] array = { "1", "2", "3", "41", "56", "41", "72", "72", "72",
            "78", "99" };

    List<Set<String>> bins = new ArrayList<>();

    for (String s : array) {
        findOrCreateBin(bins, s).add(s);
    }

    System.out.println(bins); // Prints [[1, 2, 3, 41, 56, 72, 78, 99], [41, 72], [72]]

}

private static Set<String> findOrCreateBin(List<Set<String>> bins, String s) {
    for (Set<String> bin : bins) {
        if (!bin.contains(s)) {
            return bin;
        }
    }

    Set<String> bin = new LinkedHashSet<>();
    bins.add(bin);
    return bin;
}