【问题标题】:Removing pairs of elements in an Arraylist in Java在 Java 中删除 Arraylist 中的元素对
【发布时间】:2014-08-12 18:43:30
【问题描述】:

我知道以前有人问过类似的问题,但它们通常会从 Arraylist 中删除所有指定的元素。

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

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

输出将是

[5,4,3]

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

我根本不在乎订购,因为无论如何我都会重新订购。

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

谢谢!

【问题讨论】:

  • 我根本不关心排序然后使用不允许重复值的Set
  • 请澄清您的问题 .. 我不明白 2 或 1 不会出现在我们的输出集中
  • 我也不清楚。
  • @user3218114 如果该数字仅出现两次,那么集合是否不会在其中留下一个值?如果是这样,那么这将不适用于我需要它。数字必须成对删除。
  • 如果原始数组中有四个值会怎样?删除两个,还是删除所有(两对)?

标签: java arraylist compare elements


【解决方案1】:

如果允许您对数组列表进行排序,这将变得非常简单。

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 的顺序,则必须执行其他操作,否则应该可以。

【讨论】:

  • 嗯,这个概念似乎是个好主意。它没有产生正确的输出,但我想我可以尝试修改它,看看我是否能找出问题所在。
  • 我遇到了错误,请参阅编辑 - 删除 i 后删除 i+1 会有效删除 i+2,这不是我们想要的。
  • 啊,当然,因为一切都被转移了。这完美无瑕(据我测试过),对我来说似乎是最简单的代码。非常感谢您的帮助,非常感谢!
【解决方案2】:

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

  • 遍历 ArrayList
  • 假设列表的第 i 个元素包含数字 n。
  • 如果 map.containsKey(n),map.get(n) 是上一次出现 n 的列表中的位置。
    • 从列表中删除第 i 个元素和第 map.get(n) 个元素。
    • 从地图中删除键 n。
  • 其他
    • map.put (n,i)

实施说明:

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

【讨论】:

    【解决方案3】:

    我认为最好的办法是对列表进行排序。

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

    如果您看到一个偶数总数,您将不会删除最后一个匹配项。 如果您看到奇数总计数,您将删除最后一次出现。

    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);
        }
    }
    

    享受:)

    【讨论】:

    • 这似乎接近我想要的,但是在输出上它给我留下了 1 这似乎是唯一的问题。我想这可能是因为 1 是 ArrayList 中列出的最后一个数字,而计数或某处可能有问题?
    • 1 是排序列表中的第一个元素,因此在后退时不会对其进行检查。我在最后添加了一张支票来解决这个问题。干杯,
    【解决方案4】:

    编写一个方法 removeBadPairs,它接受整数的 ArrayList 并删除任何相邻的对 如果对的左元素大于对的右元素,则列表中的整数个数。每对的 左元素是列表中的偶数索引,每对的右元素是列表中的奇数索引。 例如,假设一个名为 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] 
    

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

    【讨论】:

    【解决方案5】:

    如果由于迭代器而使用 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);
            }
        }
    }
    

    我希望这会奏效。

    【讨论】:

      猜你喜欢
      • 2016-07-23
      • 1970-01-01
      • 1970-01-01
      • 2021-01-25
      • 2023-02-07
      • 2013-02-24
      • 2020-06-02
      相关资源
      最近更新 更多