【问题标题】:Insert element to ArrayList with ascending order and no duplicate elements以升序将元素插入到 ArrayList 并且没有重复元素
【发布时间】:2011-04-05 19:31:55
【问题描述】:

我有一个家庭作业,我需要在ArrayList<Interger> 中插入或添加新元素,条件如下:

  1. 元素必须升序

  2. ArrayList<Integer>中没有重复的元素

  3. insert 方法运行 O(n) 次。

这是我在添加新元素之前检查重复元素的插入方法。

    public void insert(int x){
            //effect: Check duplicate elements if not x to the elements;
                boolean found = false;
                if(super.size()!=0){
                    for(int i=0; i<super.size(); i++){
                        if(super.get(i)==x){
                            found = true;
                        }
                    }
                }
                if(found){ return; }
                else{ super.add(x);  }
        }

我该怎么做?谢谢。

加法

这是我的班级名称 InSetExtra

public class IntSetExtra extends ArrayList<Integer> {


    private static final long serialVersionUID = 1L;

    public IntSetExtra(){
        super();
    }

    public void insert(int x){
        //effect: Check duplicate elements if not x to the elements;
            boolean found = false;
            if(super.size()!=0){
                for(int i=0; i<super.size(); i++){
                    if(super.get(i)==x){
                        found = true;
                    }
                }
            }
            if(found){ return; }
            else{ super.add(x);  }
    }

    public String toString(){
        //effect: return string of this.
        if(super.size()==0) return "[]";
        String s = "[" + super.get(0).toString();
        for(int i=1; i<super.size(); i++){
            s += ", " + super.get(i).toString();
        }
        return s += "]";
    }

}

我需要插入大尺寸的元素,例如:

IntSetExtra a, b;

    a = new IntSetExtra();
    b = new IntSetExtra();

    for(int i=0; i<30000; i++){ a.insert(2*i); }
    for(int i=0; i<30000; i++){ a.insert(i); }

    System.out.println("a sub = "+a.toString().substring(0, 37));

我该怎么办?

ps。我的导师只需要使用 ArrayList

【问题讨论】:

  • ArrayList 有什么理由这样做吗?为什么不设置?
  • 方法调用中不需要加super.(这种情况下)

标签: java arraylist


【解决方案1】:

这是一个 O(n) 中的插入方法。

public void insert(int x) {
    int pos = Collections.binarySearch(this, x);
    if (pos < 0) {
        add(-pos-1, x);
    }
}

【讨论】:

  • 嗯...这里不是加 O(n) 吗?如果是这样,您的插入方法不可能是 O(log n)。
  • 你是对的,它不是:只有查找部分在 O(n) 中。尽管如此,它仍然是最好的解决方案。
  • 嗯,它与其他答案的复杂性相同,但是是的,使用常数因子可能更有效。
【解决方案2】:

为什么不使用 TreeSet: http://download.oracle.com/javase/1.4.2/docs/api/java/util/TreeSet.html

由于这是家庭作业问题并且需要使用 ArrayList,因此我正在更改答案。

您将需要使用线性遍历和比较元素。采取相应措施:

  • 如果新元素等于当前元素,则不执行任何操作并返回。
  • 如果新元素大于当前元素则遍历到下一个。
  • 如果新元素小于当前元素,则在该索引处添加元素并返回。
  • 如果遍历时到达列表末尾,则添加新元素并返回。 (这将在列表末尾添加元素)

我在这里假设所有元素都是使用上述算法添加的。所以 ArrayList 总是排序的:)。

代码如下:

public void insert(int x) {
    for (int i = 0; i < size(); i++) {
        if (x == get(i)) {
            // if new element is equal to current element do nothing and
            // return
            return;
        } else if (x > get(i)) {
            // if new element is greater than current element traverse to
            // next.
            continue;
        }
        // code reaches here if new element is smaller than current element
        // add element at this index and return.
        add(i, x);
        return;
    }
    // if end of list is reached while traversing then add new element and
    // return. (This will add element at the end of list)
    add(x);
}

希望这会有所帮助。

【讨论】:

  • 我的instraction需要使用ArrayList
【解决方案3】:

我会这样做:(用 cmets 解释)

public void insert(int x){
    // loop through all elements
    for (int i = 0; i < size(); i++) {
        // if the element you are looking at is smaller than x, 
        // go to the next element
        if (get(i) < x) continue;
        // if the element equals x, return, because we don't add duplicates
        if (get(i) == x) return;
        // otherwise, we have found the location to add x
        add(i, x);
        return;
    }
    // we looked through all of the elements, and they were all
    // smaller than x, so we add ax to the end of the list
    add(x);
}

您发布的当前解决方案看起来基本正确,除了它不会按升序保存元素。

【讨论】:

    【解决方案4】:

    由于这是家庭作业,我假设您必须使用 ArrayList 并手动实现逻辑(而不是使用 TreeSet 作为显而易见的解决方案)。我认为以下提示应该足以让您完成实施:-)

    如果数组元素已经按升序排列,则不需要遍历整个数组。只需搜索等于或大于新元素的第一个元素。如果相等,你就有一个骗子。如果更大,在它之前插入新元素,你就完成了。如果所有现有元素都小于新元素,则将其插入到末尾。

    这将为您提供所需的 O(n) 性能。但是,作为一种改进,您可以考虑使用binary search 而不是linear

    【讨论】:

      【解决方案5】:

      为新的数据结构创建一个类。

      每当添加数据值时,对 arraylist 执行二进制搜索以确保数据值不存在。如果它已经存在,则引发异常。如果不存在,则将其插入其排序位置。

      在你的作业中记下,有一个现有的数据结构 (TreeSet) 可以执行此功能,但通过比你刚刚创建的更好的实现来实现。

      【讨论】:

      • 我的作业只需要使用 ArrayList。我更新了我的代码。
      【解决方案6】:

      一个列表是一个列表而不是一个集合,如果它表现得像一个集合,它就违反了它的契约。在 TreeSet 中插入应该是 O(log(n)) 左右...

      【讨论】:

      • 致反对者:我在添加需要 ArrayList 的说明之前写了这个,这使得答案与问题无关,但不是错误。这样的“列表”可能会破坏任何依赖于列表不变量的代码,这是一件坏事(tm)(这就是为什么恕我直言甚至不应该作为家庭作业给出)。
      【解决方案7】:

      当我想将非重复元素添加到 Set 时,我使用 TreeSet。试一试!

      【讨论】:

      • 这里确实没有理由使用列表,因为需求是专门针对 TreeSet 的。
      • Psssh,问题被标记为homework。如果 OP 应该自己编写类似 TreeSet 的逻辑来获得积分,我不会感到惊讶:) 否则这确实是一个太明显的选择。
      猜你喜欢
      • 2011-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-24
      • 2011-08-03
      相关资源
      最近更新 更多