【问题标题】:Find Range of a number from an array从数组中查找数字的范围
【发布时间】:2011-04-01 00:28:59
【问题描述】:

我只是改写我刚才问的question。 我有一个排序数组{2.0,7.8,9.0,10.5,12.3}

如果我输入 9.5 找到 9.0 和 10.5 以表明 9.5 在 9.0 和 10.5 之间(9.5 >=9.0 和

如果还有其他合适的数据结构请评论。

【问题讨论】:

  • 请接受您之前问题的答案。

标签: java arrays search


【解决方案1】:

我会那样做的

double valuebefore = 0;
            double valueafter = 0;
            double comparevalue = 9;
            foreach (var item in a)
            {
                valueafter = item;
                if (item > comparevalue)
                {
                    break;
                }
                valuebefore = item;
            }

            System.Console.WriteLine("Befor = {0} After = {1}", valuebefore, valueafter);

【讨论】:

  • 那是线性扫描。对于小型数组来说还不错,但 Emil 想要一个更优雅的解决方案(我假设 Emil 知道如何以某种方式实现它)。
【解决方案2】:

二分查找肯定是“标准”方法 - http://en.wikipedia.org/wiki/Binary_search_algorithm。速度是 O(log(N)) 而不是线性的。

在某些特殊情况下,您可以做得比 O(log(N)) 更好。但是,除非您正在处理真正巨大的数组大小并且满足这些特殊情况,否则您的二进制搜索确实是最快的方法。

【讨论】:

    【解决方案3】:

    确实,您可以使用Arrays.binarySearch 快速定位 9.0 和 10.0。

    【讨论】:

      【解决方案4】:

      对于少量的 bin,排序链表将是最优雅的。你扫描它,当你发现一个更大的数字时,你就有了范围。

      对于非常大的数字,值得将它们放入 BTree 或类似的树结构中以获得 O(log(N)) 性能。

      在 Java 中,您可以为此使用 TreeSet。

      lowerBound = bounds.headSet(yourNumber).last(); upperBound = bounds.tailSet(yourNumber).first();

      或类似的将是 O(logN) 大数。

      【讨论】:

        【解决方案5】:

        如果输入的数字在一个数组中,那么二分查找会很方便。每次搜索失败时,表示数组中不存在该数字,索引lowhigh 处的数组元素将为您提供范围。

        【讨论】:

          【解决方案6】:

          最有效的(空间和时间方面)是将其实现为修改后的二分搜索。

          一个简单(但效率较低)的解决方案是将数组替换为NavigableMap<Double, Double>,并使用floorKeyceilingKey 来查找边界值。假设您使用TreeMap,这与二分查找具有相同的复杂性。

          【讨论】:

            【解决方案7】:

            这是我刚刚为你写的一个二分搜索算法,它可以解决问题:

            import java.util.Random;
            
            public class RangeFinder {
            
                private void find(double query, double[] data) {
            
                    if (data == null || data.length == 0) {
                        throw new IllegalArgumentException("No data");
                    }
            
                    System.out.print("query " + query + ", data " + data.length + " : ");
            
                    Result result = new Result();
                    int max = data.length;
                    int min = 0;
                    while (result.lo == null && result.hi == null) {
            
                        int pos = (max - min) / 2 + min;
                        if (pos == 0 && query < data[pos]) {
                            result.hi = pos;
                        } else if (pos == (data.length - 1) && query >= data[pos]) {
                            result.lo = pos;
                        } else if (data[pos] <= query && query < data[pos + 1]) {
                            result.lo = pos;
                            result.hi = pos + 1;
                        } else if (data[pos] > query) {
                            max = pos;
                        } else {
                            min = pos;
                        }
                        result.iterations++;
                    }
                    result.print(data);
                }
            
                private class Result {
            
                    Integer lo;
                    Integer hi;
                    int iterations;
                    long start = System.nanoTime();
            
                    void print(double[] data) {
                        System.out.println(
            
                        (lo == null ? "" : data[lo] + " <= ") +
            
                        "query" +
            
                        (hi == null ? "" : " < " + data[hi]) +
            
                        " (" + iterations + " iterations in " +
            
                        ((System.nanoTime() - start) / 1000000.0) + " ms. )");
                    }
                }
            
                public static void main(String[] args) {
            
                    RangeFinder rangeFinder = new RangeFinder();
            
                    // test validation
                    try {
                        rangeFinder.find(12.4, new double[] {});
                        throw new RuntimeException("Validation failed");
                    } catch (IllegalArgumentException e) {
                        System.out.println("Validation succeeded");
                    }
                    try {
                        rangeFinder.find(12.4, null);
                        throw new RuntimeException("Validation failed");
                    } catch (IllegalArgumentException e) {
                        System.out.println("Validation succeeded");
                    }
            
                    // test edge cases with small data set
                    double[] smallDataSet = new double[] { 2.0, 7.8, 9.0, 10.5, 12.3 };
                    rangeFinder.find(0, smallDataSet);
                    rangeFinder.find(2.0, smallDataSet);
                    rangeFinder.find(7.9, smallDataSet);
                    rangeFinder.find(10.5, smallDataSet);
                    rangeFinder.find(12.3, smallDataSet);
                    rangeFinder.find(10000, smallDataSet);
            
                    // test performance with large data set
                    System.out.print("Preparing large data set...");
                    Random r = new Random();
                    double[] largeDataSet = new double[20000000];
                    largeDataSet[0] = r.nextDouble();
                    for (int n = 1; n < largeDataSet.length; n++) {
                        largeDataSet[n] = largeDataSet[n - 1] + r.nextDouble();
                    }
                    System.out.println("done");
                    rangeFinder.find(0, largeDataSet);
                    rangeFinder.find(5000000.42, largeDataSet);
                    rangeFinder.find(20000000, largeDataSet);
                }
            }
            

            【讨论】:

              猜你喜欢
              • 2014-09-20
              • 1970-01-01
              • 1970-01-01
              • 2010-09-18
              • 1970-01-01
              • 2019-07-27
              • 1970-01-01
              • 2011-07-21
              • 1970-01-01
              相关资源
              最近更新 更多