【问题标题】:list add&remove method [closed]列表添加和删除方法[关闭]
【发布时间】:2020-10-10 11:28:01
【问题描述】:

我正在尝试做一个从整数列表中删除中间元素但使用递归的方法,我对如何做基本情况感到非常困惑。当我尝试这段代码时,输​​入是 [1,3,5] 输出变成了[3,5]。

public static void removeMid(ArrayList<Integer> o){
int i=0;
    int low=0;
    int high=o.size()-1;
    int mid=(high+low)/2;
    
    
    if(o.get(i)!=mid)
    return ;
        else if(o.get(i)==mid) {
            o.remove(i);
    System.out.println(o.get(i)); //return mid element
        
    System.out.println(o);
    removeMid(o);
        }}```
    
    

【问题讨论】:

  • o.get(i)!=mid 在这里您将索引与列表值进行比较。这没有任何意义。

标签: java list data-structures


【解决方案1】:

这取决于定义什么是中间元素

假设中间元素是放在中间索引的那个,你应该使用List/ArrayList的方法E remove(int index)

您可能希望将删除限制在输入列表大小为奇数的情况下。

public static void removeMid(ArrayList<Integer> o) {
    if (o.size() > 1 && o.size() % 2 != 0) {
        int removed = o.remove(o.size() / 2);
        System.out.println("removed element: " + removed);
    } else {
        System.out.println("no middle element to remove is available");
    }
}

如果你需要移除一个中间值,你可以对输入列表进行排序,然后像之前一样移除中间索引处的一个元素:

public static void removeMidValue(ArrayList<Integer> o) {
    Collections.sort(o);
    removeMid(o);
}

更新
递归解决方案包括找到minmax 元素,删除它们,递归调用以从剩余列表中删除中间值,并在从递归调用返回时恢复minmax 值。递归的退出条件是剩余列表仅包含一个要删除的元素。

要解决的另一点是如何恢复 minmax 元素 - 可以选择在删除/恢复元素时使用它们的索引,或者只是添加 minmax 值返回列表从而改变初始顺序。

话虽如此,保持顺序的递归解决方案可能如下:

public static void removeMidRecursive(ArrayList<Integer> o) {
    System.out.println("recursive: " + o);
    if (o.size() % 2 == 0) {
        System.out.println("list size is even, no middle element to remove");
    } else if (o.size() == 1) {
        int mid = o.remove(0);
        System.out.println("removed mid element: " + mid);
    } else {
        // find indexes of min and max elements
        int minId = 0;
        int maxId = 0;
        for (int i = 1; i < o.size(); i++) {
            int val = o.get(i);
            if (val < o.get(minId)) {
                minId = i;
            } else if (val >= o.get(maxId)) {
                maxId = i;
            }
        }

        // sort the indexes
        int tMin = Math.min(minId, maxId);
        int tMax = Math.max(minId, maxId);
        // start removing from bigger index and store the value
        // using `E remove(int index)`
        Integer atMax = o.remove(tMax);
        // System.out.printf("removed o[%d]=%d%n", tMax, atMax);
        Integer atMin = o.remove(tMin);
        // System.out.printf("removed o[%d]=%d%n", tMin, atMin);
        
        removeMidRecursive(o);

        // restore the values by insertig at appropriate index with a correction
        if (tMin > 0) o.add(tMin - 1, atMin); else o.add(0, atMin);
        if (tMax > 0) o.add(tMax - 1, atMax); else o.add(0, atMax);
        
        System.out.println("restored: " + o);
    }
}

测试:

ArrayList<Integer> arr = new ArrayList<>(Arrays.asList(3, 5, 1, 1, 7, 6, 7));
System.out.println(arr);
removeMidRecursive(arr);
System.out.println(arr);

System.out.println("------------------");

arr = new ArrayList<>(Arrays.asList(6, 4, 1, 4, 2, 1, 4));
System.out.println(arr);
removeMidRecursive(arr);
System.out.println(arr);

输出

[3, 5, 1, 1, 7, 6, 7]
recursive: [3, 5, 1, 1, 7, 6, 7]
recursive: [3, 5, 1, 7, 6]
recursive: [3, 5, 6]
recursive: [5]
removed mid element: 5
restored: [3, 6]
restored: [3, 1, 7, 6]
restored: [3, 1, 1, 7, 6, 7]
[3, 1, 1, 7, 6, 7]
------------------
[6, 4, 1, 4, 2, 1, 4]
recursive: [6, 4, 1, 4, 2, 1, 4]
recursive: [4, 4, 2, 1, 4]
recursive: [4, 4, 2]
recursive: [4]
removed mid element: 4
restored: [4, 2]
restored: [4, 2, 1, 4]
restored: [6, 1, 4, 2, 1, 4]
[6, 1, 4, 2, 1, 4]

不保持原顺序的递归移除要简单得多,而且是使用另一个List的方法boolean remove(Object item)

public static void removeMidAndShuffle(ArrayList<Integer> o) {
    if (o.size() % 2 == 0) {
        System.out.println("list size is even, no middle element to remove");
    } else if (o.size() == 1) {
        int mid = o.remove(0);
        System.out.println("removed mid element: " + mid);
    } else {
        Integer min = Integer.MAX_VALUE;
        Integer max = Integer.MIN_VALUE;
        for (Integer x : o) {
            min = Math.min(min, x);
            max = Math.max(max, x);
        }
        o.remove(min);
        o.remove(max);
        removeMidAndShuffle(o);
        o.add(min);
        o.add(max);
    }
}

它的输出:

[3, 5, 1, 1, 7, 6, 7]
removed mid element: 5
[3, 6, 1, 7, 1, 7]
---------
[6, 4, 1, 4, 2, 1, 4]
removed mid element: 4
[2, 4, 1, 4, 1, 6]

【讨论】:

  • 感谢您的解决方案,但我必须使用递归来解决它
  • 我试图根据你的解决方案使其递归它有效地删除了中间元素但它最终删除了列表中的所有元素任何想法我如何终止它我只需要它删除一次`如果(o.size() ==0 && o.size() % 2 == 0) { return; } 其他 { o.remove(o.size() / 2); System.out.println(o);移除中间(o); }}`
  • 所以你只需要在数组中找到一个中间元素并只删除这个元素而不使用库sorting?
  • @E00X,你可以查看更新
【解决方案2】:

这是一个最简单的情况,它通过递归“迭代” ArrayList 中的值。请注意,我们有一个额外的参数i,我们将传递它来跟踪我们在列表中的位置。这只是根据 INDEX 删除中间位置的任何内容。它不考虑列表中包含的值:

  public static void main(String[] args) {
    ArrayList<Integer> numbers = new ArrayList<Integer>();
    numbers.add(1);
    numbers.add(3);
    numbers.add(5);

    System.out.println("Before: " + numbers.toString());
    removeMid(numbers, 0);
    System.out.println("After: " + numbers.toString());
  }

  public static void removeMid(ArrayList<Integer> o, int i){
    if (o!=null && o.size()>0) {
      // you didn't give a clear specification for "middle"
      int mid=o.size() / 2; // to the right of middle, for even sized lists 
      if (i == mid) {
        o.remove(i);
      }
      else {
        removeMid(o, i+1);
      }
    }
  }

输出:

Before: [1, 3, 5]
After: [1, 5]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    相关资源
    最近更新 更多