已排序的插入位置

时间:2017-08-23 05:24:59

标签: java algorithm binary-search

问题陈述:给定排序数组和目标值,如果找到目标,则返回索引。如果没有,请返回索引按顺序插入的索引。 您可以假设数组中没有重复项。

以下是一些例子。

[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0

我的代码

public class Solution {
public int searchInsert(ArrayList<Integer> a, int b) {
    int low = 0, high = a.size()-1;
    int mid = (low+high)/2; 
    int retIndex = mid;
    while(low<=high){
        if(a.get(mid)<b){
            low = mid+1;
            mid = (low+high)/2;
            retIndex = low;
        }
        else{
            high = mid-1;
            mid = (low+high)/2;
            if(high<0) retIndex = 0;
            else retIndex = high;
        }
    }
    return retIndex;
}
}

但是这段代码存在一些缺陷(在某些大输入上返回1个或更少的索引,这对于放在这里是徒劳的)因为你可以直接检查here,我是无法弄清楚。谁能指出我的错误?或者这个问题的正确代码是什么?

编辑:我正在展示它为其提供意外输出的精确输入。

A : [ 3, 4, 18, 19, 20, 27, 28, 31, 36, 42, 44, 71, 72, 75, 82, 86, 88, 97, 100, 103, 105, 107, 110, 116, 118, 119, 121, 122, 140, 141, 142, 155, 157, 166, 176, 184, 190, 199, 201, 210, 212, 220, 225, 234, 235, 236, 238, 244, 259, 265, 266, 280, 283, 285, 293, 299, 309, 312, 317, 335, 341, 352, 354, 360, 365, 368, 370, 379, 386, 391, 400, 405, 410, 414, 416, 428, 433, 437, 438, 445, 453, 457, 458, 472, 476, 480, 485, 489, 491, 493, 501, 502, 505, 510, 511, 520, 526, 535, 557, 574, 593, 595, 604, 605, 612, 629, 632, 633, 634, 642, 647, 653, 654, 656, 658, 686, 689, 690, 691, 709, 716, 717, 737, 738, 746, 759, 765, 775, 778, 783, 786, 787, 791, 797, 801, 806, 815, 820, 822, 823, 832, 839, 841, 847, 859, 873, 877, 880, 886, 904, 909, 911, 917, 919, 937, 946, 948, 951, 961, 971, 979, 980, 986, 993 ]
B : 902

此输入的预期返回值为:149
我输入的代码返回值为:148

3 个答案:

答案 0 :(得分:1)

对于最基本的测试用例,您的代码将失败:

[1,3,5,6],5→2

您应该在价值a.get(mid) > ba.get(mid)== b时处理这种情况 分别。此外,您无需单独维护变量retIndex

所以将代码更改为:

    while(low<=high){
        if(a.get(mid)<b){
            low = mid+1;
            mid = (low+high)/2;                
        }
        else if(a.get(mid) > b){
            high = mid-1;
            mid = (low+high)/2;                
        }
        else return mid;
    }

    return low;//handles the case when no match is found.

答案 1 :(得分:1)

您需要处理相等性并更改更大分支的返回值。

while(low<=high){
    if (a.get(mid) == b) return mid;
    else if(a.get(mid)<b){
        low = mid+1;
        mid = (low+high)/2;
        retIndex = low;
    }
    else {
        high = mid-1;
        retIndex = mid;
        mid = (low+high)/2;
    }
}

答案 2 :(得分:1)

这是怎么回事?

public class Solution {
public int searchInsert(ArrayList<Integer> a, int b) {
    int low = 0;
    int high = a.size();
    int candidateIdx = (low + high) / 2;
    int candidateValue;
    int prevCandidateIdx = -1;

    while (low != high ) {
        candidateValue = a.get(candidateIdx);
        if (candidateValue == b) {
            break;
        } else if (candidateValue < b && prevCandidateIdx == candidateIdx -1) {
            candidateIdx++;
            break;
        } else if (candidateValue < b) {
            low = candidateIdx;
        } else if (prevCandidateIdx == candidateIdx + 1) {
            break;
        } else {
            high = candidateIdx;
        }
        prevCandidateIdx = candidateIdx;
        candidateIdx = (low + high)/2;
    }
    return candidateIdx;
}
}