在Java中删除Arraylist中的元素对

时间:2014-08-12 18:43:31

标签: java arraylist compare elements

我之前已经问过类似的问题,但它们通常会从Arraylist中删除所有指定的元素。

我需要做的是从我的ArrayList中删除一对值(如果一个数字出现3次,它将删除该元素的2个副本并留下其中的1个)。更一般地说,如果出现一个数字,则奇数次数为1,如果出现一个数字偶数次则将它们全部删除。因此,如果我的Arraylist就是这样的话

[5,4,3,3,2,1,2,3,1],

输出将是

[5,4,3]

由于数字“2”出现两次,因此完全删除。与数字“1”相同。但由于数字“3”出现三次,它会将其中一个留在ArrayList中,因为我只想成对删除数字。

我根本不在乎订购,因为我还是要重新订购它。

有人对此有任何建议吗?我想我可以使用for循环来反复比较每个值,但它似乎效率低下,所以我很好奇是否有更好的方法。

谢谢!

5 个答案:

答案 0 :(得分:2)

如果你被允许对arraylist进行排序,这变得非常简单。

public void removePairedElements(ArrayList<Integer> a){

    Collections.sort(a); //Sort a

    int i = 0;
    while(i < a.size() - 1){
      //Check if i and i+1 are the same element. If so, remove both
      if(a.get(i).equals(a.get(i+1))){
        //Remove i twice - effectively removes i and i+1
        a.remove(i);
        a.remove(i);

        //Move i *back* one index, which is equivalent to 
        //moving forward one because we just removed two elements.
        //Prevent i from becoming negative though.
        i = Math.max(0, (i - 1));
      }
      else{
        i++;
      }
    }
}

O(n log n)时间和O(1)空间。可能是最干净的答案。如果您不允许更改arraylist的顺序,则必须执行其他操作,否则这应该有效。

答案 1 :(得分:1)

您可以使用地图作为帮助。

  • 遍历ArrayList
  • 让我们说列表的第i个元素包含数字n。
  • 如果是map.containsKey(n),则map.get(n)是前一次出现的n列表中的位置。
    • 从列表中删除第i个元素和map.get(n)&#39;
    • 从地图中删除密钥n。
  • 否则
    • map.put(n,i)

实施说明:

不要使用增强的for循环迭代列表(因为它不允许删除元素)。迭代列表的索引。这将允许您通过索引删除元素(但请记住,当您删除第i个元素时,前一个i + 1元素将成为新的第i个元素。)

答案 2 :(得分:1)

我认为你最好的选择是对名单进行排序。

然后,向后,如果你看到同一个,同时跟踪当前整数的总数,则删除整数。

如果您看到偶数总数,则不会删除最后一次出现。 如果你看到一个奇怪的总数,你将删除最后一次出现。

public void removePairElementsFrom(Arraylist<Integer> myArrayList)
{
    if (myArrayList == null)
    {
        return null;
    }

    int arrayLength = myArrayList.size();

    if (arrayLegnth == 1)
    {
        return myArrayList;
    )

    Collections.sort(myArrayList);

    int lastSeenInt = myArrayList.get(arrayLength - 1);
    int lastSeenIntCount = 1;

    for (int i = arrayLength - 2; i >= 0; --i)
    {
        if (myArrayList[i] == lastSeenInt)
        {
            myArrayList.remove(i+1);
            ++lastSeenIntCount;
        }
        else
        {
            if ((lastSeenIntCount % 2) == 0)
            {
                myArrayList.remove(i+1);
            }

            lastSeenInt = myArrayList.get(i);
            lastSeenIntCount = 1;
        }
    }

    if ((lastSeenIntCount % 2) == 0)
    {
        myArrayList.remove(0);
    }
}

享受:)

答案 3 :(得分:0)

编写一个方法removeBadPairs,它接受一个整数的ArrayList并删除任何相邻的对 如果该对的左侧元素大于该对的右侧元素,则列表中的整数。每一双 left元素是列表中的偶数索引,每个对的右元素是列表中的奇数索引。 例如,假设名为list的变量存储以下元素值:

[3, 7, 9, 2, 5, 5, 8, 5, 6, 3, 4, 7, 3, 1]

我们可以将此列表视为一对序列:(3,7),(9,2),(5,5),(8,5),(6,3),(4,7) ,(3,1)。对(9, 2),(8,5),(6,3)和(3,1)是“坏”因为左元素大于右元素所以这些对 应该删除。因此removeBadPairs(list);的调用将更改列表以存储以下内容 元素值:

[3, 7, 5, 5, 4, 7] 

如果列表的长度为奇数,则最后一个元素不是一对的一部分,也被视为“坏”;这应该 因此,您的方法将删除。 如果传入空列表,则在调用结束时列表仍应为空。你可能会认为 传递的列表不为空。您不能使用任何其他数组,列表或其他数据结构来帮助您解决 这个问题,虽然你可以创建任意数量的简单变量。

答案 4 :(得分:0)

如果由于迭代器而使用For循环从列表的开头开始,则会出现错误。所以我有另一种方式。

class RemoveBadPairs {    
    Public Static void main() {
        ArrayList numbersList = new ArrayList();
        numberslist={3,7,9,2,5,5,8,5,6,3,4,7,3,1,7};   
        System.out.println("Original List...");
        for (e in : numbersList) {
            System.out.print("{0},", e);
        }
        if (((numbersList.Count % 2)!= 0)) {
            numbersList.RemoveAt((numbersList.Count - 1));
        }
        for (int i = (numbersList.Count - 1); (i <= 0); i = (i + -2)) {
            if ((numbersList[i] < numbersList[(i - 1)])) {
                numbersList.RemoveRange((i - 1), 2);
            }   
        }
        System.out.println("Final List...");
        for (e in : numbersList) {
            System.out.print(","+ e);
        }
    }
}

我希望这会奏效。