查找二进制搜索失败的情况

时间:2016-11-18 14:17:57

标签: java algorithm

我正在尝试解决一个非常有趣的编程挑战,而且我有点想法为什么我的代码失败了。这是:

  

编写一个函数,给定一个列表和一个目标总和,返回   任何两个不同元素的从零开始的索引,其总和等于   目标总和。如果没有这样的元素,函数应该   返回null。   例如,findTwoSum(new int [] {1,3,5,7,9},12)应返回以下任何索引元组:

1, 4 (3 + 9 = 12)
2, 3 (5 + 7 = 12)
3, 2 (7 + 5 = 12)
4, 1 (9 + 3 = 12)

应该简单吧?所以这是我的功能:

public static int[] findTwoSum(int[] list, int sum) {
        int[] indices = null;
        for(int i = 0; i < list.length; i++) {
            int currentNum = list[i];
            int findNum = sum - currentNum;
            int length = list.length;
            int min = i;
            int max = length-1;

            while(max >= min) {
                int guess = (max+min)/2;

                if(list[guess] == findNum) {
                  return new int[] {i,guess};
                } 

                if(list[guess] < findNum) {
                    min = guess + 1;
                }

                if(list[guess] > findNum) {
                    max = guess - 1;
                }
            }

        }


        return indices;
    }

代码非常简单,对于数组中的每个元素,它都会尝试使用二进制搜索来查找另一个元素,以便它们的总和等于提供的sum。我已经测试了这段代码,我找不到失败的场景,假设提供的数组已经排序。但是,当我在TestDome上运行此代码时,最后一种情况失败了,它在某种程度上是错误的解决方案。有人能指出这种方法有什么问题吗?

3 个答案:

答案 0 :(得分:3)

代码假定列表已排序。问题陈述没有说明元素的顺序,所以你需要自己对数组进行排序。由于您需要索引,因此需要对值对和索引进行排序。

更快的方法是将数据放入带有计数和原始索引的哈希映射中,并检查列表中每个Target - n是否存在n。当Target等于2*n时,您需要针对特殊情况的计数。

答案 1 :(得分:0)

基于作者关于初始列表的排序顺序的问题和说明,似乎初始列表没有排序。因此需要对列表进行排序,并且原始索引需要单独存储在另一个列表中。

在对数组进行排序并记录原始索引之后,让我们说arr[]包含排序列表,indices[]包含arr[]中相应元素的原始索引。换句话说,indices[i]给出了元素arr[i]的原始索引。

现在,您可以按照2-SUM算法查找对:

  • 初始化两个索引变量以查找候选项 排序数组中的元素。

    • 首先初始化到最左边的索引:l = 0
    • 初始化最右边的索引:r = ar_size-1
  • 循环,而l&lt;河

    • 如果(arr [l] + arr [r] == sum)则返回对(indices [l],indices [r])
    • 如果(arr [l] + arr [r]&lt; sum)则l ++
    • 其他r--
  • 整个数组中没有候选人 - 返回NULL

您也可以使用二进制搜索技术代替2-SUM程序。

希望它有所帮助!!

答案 2 :(得分:0)

试试这个解决方案。它对数组进行排序并使用二进制搜索来定位第二个元素,该元素必须是 sum - n

如果找到匹配的对,则在原始数组中查找它以确定原始索引:

public static int[] findTwoSum(int[] list, int sum) {
    int len = list.length;
    int[] sortedList= Arrays.copyOf(list, len);
    Arrays.sort(sortedList);
    for (int i = 0; i < len; i++) {
        int m = list[i];
        int j = Arrays.binarySearch(sortedList, sum - m);
        if (j >= 0 && i != j)
            return new int[] { i, findIndex(list, sortedList[j]) };
    }
    return null;
}

public static int findIndex(int[] list, int m) {
    int len = list.length;
    for (int i = 0; i < len; i++) {
        if (list[i] == m)
            return i;
    }
    return -1;
}