在ArrayList中查找所需的最小双打数量

时间:2015-06-12 20:14:29

标签: java arraylist collections

我有一个填充了Double值的ArrayList,并且根据用户输入(int),我需要从这个List中找到输入的最小双打数量的索引。例如,如果用户输入5,并且ArrayList看起来如此(实际上要大得多):

-6789.44658
-27239.73827
-12365.78370
-456.789457
-4768.42579
-15263.26399
-15263.26399
-0.0
-24688.7289

我会得到1, 5, 8, 2, 6(从最小到最大的5个最小双打的顺序并不重要)。这是我到目前为止所做的:

int[] indices = new int[input];
List<Double> copy = new ArrayList<Double>(origList); //origList is list of Doubles

for (int t = 0; t < input; t++)
{
    indices[t] = origList.indexOf(Collections.min(copy));
    copy.remove(Collections.min(copy));
}

但是有两个问题:

  1. 效率非常低
  2. 在上面给出的示例ArrayList中,有两个值是 相同(甚至可能有三个相同的值)。如果 相同的值是副本中的最低值,因为indexOf() 返回该值中第一次出现的索引 origList,相同的索引返回两次。但是,没有一个指数 可以是一样的。
  3. 感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

一种解决方案是使用您的origList并在使用值填充TreeMap<Double, List<Integer>>后迭代它。密钥是你的double,列表是具有该值的索引列表。

TreeMap在向其添加项目时维护顺序,因此无需执行其他排序步骤。输入TreeMap是log(n)所以找时间最小的n个索引应该是O(log N)。

   int input = 5;
   List<Double> origList = new ArrayList<Double>();

   origList.add(-6789.44658);
   origList.add(-27239.73827);
   origList.add(-12365.78370);
   origList.add(-456.789457);
   origList.add(-4768.42579);
   origList.add(-15263.26399);
   origList.add(-15263.26399);
   origList.add(-0.0);
   origList.add(-24688.7289);

   TreeMap<Double, List<Integer>> smallest = new TreeMap<Double, List<Integer>>();
   for (int i = 0; i < origList.size(); i++) {
       double d = origList.get(i);
       List<Integer> list = smallest.get(d);
       if (list == null) {
           list = new ArrayList<Integer>();
           smallest.put(d, list);
       }
       list.add(i);
   }

现在您已经将值的排序映射到它们的索引,您只需要从该映射中获取前n个键并获取它们的值,然后就完成了。

   List<Integer> indices = new ArrayList<Integer>();

   for (Double key : smallest.keySet()) {
       List<Integer> list = smallest.get(key);
       for (Integer index : list) {
           indices.add(index);
           if (indices.size() == input) break;
       }
       if (indices.size() == input) break;
   }

   System.out.println(smallest);
   System.out.println(indices);

以上代码生成以下地图:

{-27239.73827=[1], -24688.7289=[8], -15263.26399=[5, 6], -12365.7837=[2], -6789.44658=[0], -4768.42579=[4], -456.789457=[3], -0.0=[7]}

以及以下最终输出:

[1, 8, 5, 6, 2]

答案 1 :(得分:0)

这样的事情怎么样?

public int[] getLowest(List<Double> list, int howMany) {
    int[] indices = new int[howMany];

    List<Double> copy = new ArrayList<>(list);
    Collections.sort(copy);

    List<Double> lowest = new ArrayList<>();
    for (int i = 0; i < howMany; i++) {
        lowest.add(copy.get(i));
    }

    int indicesIndex = 0;
    for (int d = 0; d < list.size(); d++) {
        if (lowest.contains(list.get(d))) {
            indices[indicesIndex] = d;
            indicesIndex++;
        }
    }

    return indices;
}

答案 2 :(得分:0)

我遍历双列表,保留n个最小值并忽略重复。

这是结果。

[(-27239.73827, 1), (-24688.7289, 8), (-15263.26399, 5), (-12365.7837, 2), 
 (-6789.44658, 0)]

我意识到我归还了双打和指数。如果愿意,您可以从Minimum数组中获取索引。

此代码以O(n)运行。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class NSmallest implements Runnable {

    private static final double LARGE_DOUBLE = 1.0E100;

    private int n;

    public static void main(String[] args) {
        int n = 5;
        new NSmallest(n).run();
    }

    public NSmallest(int n) {
        this.n = n;
    }

    @Override
    public void run() {
        List<Double> numbers = loadList();
        Minimum[] minimums = initializeMinimums();

        for (int i = 0; i < numbers.size(); i++) {
            double value = numbers.get(i);
            minimums = getMinimum(minimums, value, i);
        }

        System.out.println(Arrays.toString(minimums));
    }

    private List<Double> loadList() {
        List<Double> numbers = new ArrayList<>();
        numbers.add(Double.valueOf(-6789.44658));
        numbers.add(Double.valueOf(-27239.73827));
        numbers.add(Double.valueOf(-12365.78370));
        numbers.add(Double.valueOf(-456.789457));
        numbers.add(Double.valueOf(-4768.42579));
        numbers.add(Double.valueOf(-15263.26399));
        numbers.add(Double.valueOf(-15263.26399));
        numbers.add(Double.valueOf(-0.0));
        numbers.add(Double.valueOf(-24688.7289));

        return numbers;
    }

    private Minimum[] initializeMinimums() {
        Minimum[] minimums = new Minimum[n];

        for (int i = 0; i < minimums.length; i++) {
            minimums[i] = new Minimum(LARGE_DOUBLE, -1);
        }

        return minimums;
    }

    private Minimum[] getMinimum(Minimum[] minimums, double value, int index) {
        for (int i = 0; i < minimums.length; i++) {
            double number = minimums[i].getNumber();
            if (value == number) {
                break;
            } else if (value < number) {
                int j = minimums.length - 2;
                while (j >= i) {
                    minimums[j + 1].setIndex(minimums[j].getIndex());
                    minimums[j + 1].setNumber(minimums[j].getNumber());
                    j--;
                }
                minimums[i].setIndex(index);
                minimums[i].setNumber(value);
                break;
            }
        }

        return minimums;
    }

    public class Minimum {
        private double number;
        private int index;

        public Minimum(double number, int index) {
            this.number = number;
            this.index = index;
        }

        public double getNumber() {
            return number;
        }

        public int getIndex() {
            return index;
        }

        public void setNumber(double number) {
            this.number = number;
        }

        public void setIndex(int index) {
            this.index = index;
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append("(");
            builder.append(number);
            builder.append(", ");
            builder.append(index);
            builder.append(")");
            return builder.toString();
        }

    }
}