如何在Java中从整数数组列表中删除重复的子整数数组?

5

给你一个嵌套的数组列表,例如: list = [[-1,2,1],[-2,-2,4],[-1,2,-1],[-1,-2,3],[-1,2,-1]]

我想要得到这样的输出: [[-1,2,1],[-2,-2,4],[-1,-2,3]]

但使用的代码不太可能得到这样的输出...

for(int i=0;i<list.size();i++){
for(int j=i+1;j<list.size();j++){
if(list.get(i).eqauls(list.get(j)))
 {
 list.remove(list.get(j));
  }
  }
  }
 System.out.println(list);

我已经这样做了,但是还是有重复的。所以我用另一种方式解决了这个问题,就像这样...
List<List<Integer>> list2=  new ArrayList<List<Integer>>();
for(int i=0;i<list.size();i++){
for(int j=i+1;j<list.size();j++){
if(!list.get(i).eqauls(list.get(j)))
 {
 List<Integer> p= new ArrayList<Integer>();
 for(int m=0;m<list.size();m++){
 for(int n=0;n<list.get(i).size();n++){
 p.add(list.get(i).get(m));
 list2.add(p);
 }
 }
 }
System.out.println(list2);

输出:运行时错误 在这种情况下,我应该怎么做……只使用数组列表数据结构……


5
你认为[-1,2,1][-1,2,-1]是相同的吗?请明确一下,这两者被认为是相同的基础是什么? - Arun Gowda
你的 j 上限似乎有误。 - Colm Bhandal
你在问题中写道:“输出:运行时错误”。也许你可以[编辑]你的问题,并发布实际的错误消息和堆栈跟踪?我猜测这是因为你代码中的这一行:List<List<Integer>> list2= new ArrayList<List<Integer>>();。我没有看到你在哪里填充了list2。你正在创建一个空列表。 - Abra
4个回答

2

策略

我们可以构建一棵树形数据结构,其路径恰好是您的主列表中包含的唯一子列表。一旦构建了树,我们可以对其进行迭代,例如使用递归算法,并重新构建一个没有重复项的列表。

代码

import java.util.*;

public class ListUnduper{

     public static void main(String []args){
        Tree root = new Tree();
        List<List<Integer>> list = new ArrayList<>();
        List<Integer> first = new ArrayList<Integer>(); 
        first.add(1); first.add(2);
        List<Integer> second = new ArrayList<Integer>(); 
        //Add more lists here if you like
        list.add(first); list.add(second);
        for(int i=0;i<list.size();i++){
          List<Integer> inner = list.get(i);
          Tree current = root;
          for(int j=i+1;j<inner.size();j++){
            int nextElement = inner.get(j);        
            if(!current.children.containsKey(nextElement)){
              current.children.put(nextElement, new Tree());
            }
            current = current.children.get(nextElement);
           }
        }

        List<List<Integer>> master = new ArrayList<List<Integer>>();
        List<Integer> emptyPrefix = new ArrayList<Integer>();
        addAllToList(emptyPrefix, master, root);    

        //master now should contain all non-dupes 
     }

    static void addAllToList(List<Integer> prefix, List<List<Integer>> master, Tree tree){
      for(Map.Entry<Integer,Tree> entry : tree.children.entrySet()){
        Tree nextTree = entry.getValue();  
        //I believe this makes a deep copy
        List<Integer> nextPrefix = new ArrayList<>(prefix);
        nextPrefix.add(entry.getKey());
        if(nextTree.children.isEmpty()){
          master.add(nextPrefix);
        }
        else{
          addAllToList(nextPrefix, master, tree);
        }
      }
    }
}

class Tree{
  HashMap<Integer, Tree> children = new HashMap<Integer, Tree>();
}

警告:如果您的列表很大,则使用递归可能会导致堆栈溢出错误。在这种情况下,建议切换到使用while循环,但在这种情况下,算法可能更难编码。

元素顺序注意事项

正如这个备选答案所指出的那样,主列表中列表的原始顺序可能很重要。上述解决方案不能保证保留这样的顺序。


1
你的代码存在几个问题。例如,你正在使用原始类型,并且将基本类型用作类型参数(这是不可编译的)。 - MC Emperor
@MCEmperor V. 确实。懒惰算法草图已被可行的代码所取代。 - Colm Bhandal

1

我猜这可能是一项学校任务,旨在让你练习使用列表和迭代器以及equals()方法,甚至可能涉及ComparatorComparable。我很确定你还没有学习流API,但由于你的代码使用了List,这意味着你已经学习了集合框架,所以我不需要向你解释Set是什么。无论如何,你的任务可以使用下面的代码中展示的流API集合框架轻松完成。(请注意,下面的代码使用了Java 9中引入的方法。)
/* Required imports
 * 
 * import java.util.List;
 * import java.util.Set;
 * import java.util.stream.Collectors;
 */
List<List<Integer>> list2 = List.of(List.of(-1,2,1),
                                    List.of(-2,-2,4),
                                    List.of(-1,2,-1),
                                    List.of(-1,-2,3),
                                    List.of(-1,2,-1));
Set<List<Integer>> noDups = list2.stream()
                                 .collect(Collectors.toSet());
System.out.println(noDups);

运行上述代码会产生以下输出。
(请注意,迭代一个Set不保证任何特殊的顺序。)
[[-2, -2, 4], [-1, -2, 3], [-1, 2, -1], [-1, 2, 1]]

参考接口java.util.List的方法equals()

编辑

由于Colm Bhandal的评论,并受到artmmslv答案的启发,如果顺序很重要,那么下面稍作修改的代码将保持顺序。

List<List<Integer>> list2 = List.of(List.of(-1,2,1),
                                    List.of(-2,-2,4),
                                    List.of(-1,2,-1),
                                    List.of(-1,-2,3),
                                    List.of(-1,2,-1));
Set<List<Integer>> noDups = list2.stream()
                                 .collect(LinkedHashSet::new,
                                          LinkedHashSet::add,
                                          LinkedHashSet::addAll);
System.out.println(noDups);

这段代码的输出为:
[[-1, 2, 1], [-2, -2, 4], [-1, 2, -1], [-1, -2, 3]]

0

将你的子数组放入LinkedHashSet

该集合按添加顺序存储对象(不存储相等的对象)


简洁明了,回答了问题,但我认为你应该添加一些代码来演示如何实现你提出的解决方案。 - Abra

0

你需要自己编写代码,没有任何魔法函数可以替你完成。

你可以在下面看到示例代码。

const input = [[-1,2,1],[-2,-2,4],[-1,2,-1],[-1,-2,3],[-1,2,-1]]

const removeDuplicate = list => {
  const set = new Set()
  for (const item of list) {
     set.add(item.join('|'))
  }
  const result = Array.from(set).map(strItem => {
    const resultItem = strItem.split('|').map(item => parseInt(item))
    return resultItem
  })
  return result
}

const result = removeDuplicate(input)

console.log(result)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接