如何在给定特定范围的列表中找到一对数字?

时间:2019-05-04 19:55:47

标签: math search range

问题是这样的:

给定一个 N 个数字的数组,在数组中找到两个数字,这样它们的范围(最大值-最小值)值为 K

例如:

输入:

5 3
25 9 1 6 8

输出:

9 6

到目前为止,我尝试过的工作是首先对数组进行排序,然后使用嵌套循环找到两个互补数。但是,由于这是一种蛮力方法,所以我认为它不如其他可能的方法有效。

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), k = sc.nextInt();
        int[] arr = new int[n];
        for(int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }
        Arrays.sort(arr);
        int count = 0;
        int a, b;
        for(int i = 0; i < n; i++) {
            for(int j = i; j < n; j++) {
                if(Math.max(arr[i], arr[j]) - Math.min(arr[i], arr[j]) == k) {
                    a = arr[i];
                    b = arr[j];
                }
            }
        }
        System.out.println(a + " " + b);
    }
}

如果解决方案采用代码(任何语言),将不胜感激。

1 个答案:

答案 0 :(得分:1)

以下是Python 3中解决您问题的代码。即使您不了解Python,这也应该很容易理解。

此例程使用您对数组进行排序的想法,但是我使用了两个变量leftright(它们定义了数组中的两个位置),每个变量仅使数组通过一个。因此,除了排序以外,我的代码的时间效率是O(N)。排序使整个例程O(N log N)。这比您的代码O(N^2)更好。

我从不使用N的输入值,因为Python可以轻松处理数组的实际大小。我在数组的末尾添加了一个哨兵值,以使内部短循环更简单,更快捷。这涉及到另一个遍历数组以计算前哨值的过程,但这几乎没有增加运行时间。可以减少数组访问的次数,但要花几行代码,我会留给您。我添加了输入提示以帮助我进行测试-您可以删除这些提示以使我的结果更接近于您想要的结果。我的代码先打印两个数字中较大的一个,然后打印较小的数字,这与您的示例输出匹配。但是您可能希望两个数字的顺序与原始的未排序数组中的顺序相匹配-如果是这种情况,我也将让您处理(我看到了多种实现方法)。

# Get input
N, K = [int(s) for s in input('Input N and K: ').split()]
arr = [int(s) for s in input('Input the array: ').split()]

arr.sort()
sentinel = max(arr) + K + 2
arr.append(sentinel)
left = right = 0
while arr[right] < sentinel:
    # Move the right index until the difference is too large
    while arr[right] - arr[left] < K:
        right += 1
    # Move the left index until the difference is too small
    while arr[right] - arr[left] > K:
        left += 1
    # Check if we are done
    if arr[right] - arr[left] == K:
        print(arr[right], arr[left])
        break