📜  在Java按排序的数组搜索相等,更大或更小的对象

📅  最后修改于: 2021-04-24 20:37:06             🧑  作者: Mango

给定已排序整数数组,搜索键和搜索首选项会找到数组位置。搜索首选项可以是:
1)EQUAL –仅搜索等号或-1(如果未找到)。这是常规的二进制搜索。
2)EQUAL_OR_SMALLER –仅搜索相等的键或最接近的较小的键。 -1(如果找不到)。
3)EQUAL_OR_BIGGER –仅搜索相等的键或最接近的较大键。 -1(如果找不到)。

例子:

Input : { 0, 2, 4, 6 }, key -1, EQUAL 
Output : -1

Input : { 0, 2, 4, 6 }, key -1, EQUAL_OR_BIGGER
Output : 0

Input : { 0, 2, 4, 6 }, key 7, EQUAL_OR_BIGGER
Output : -1

Input : { 0, 2, 4, 6 }, key 7, EQUAL_OR_SMALLER
Output : 3

在常规的二分查找算法中,评估和划分的作用是子数组的大小大于0。
在我们的情况下,如果要保留单个函数,则需要在size = 2的子数组中执行最终评估。仅在子数组size == 2中才能检查EQUAL_OR_SMALLER和EQUAL_OR_BIGGER条件。

在下面的代码中, SC代表搜索条件

public class BinarySearchEqualOrClose {
  
    private static void printResult(int key, int pos,
                                    SC sC)
    {
        System.out.println("" + key + ", " + sC + ":" + pos);
    }
  
    enum SC {
        EQUAL,
        EQUAL_OR_BIGGER,
        EQUAL_OR_SMALLER
    };
  
    public static int searchEqualOrClose(int key, int[] arr, SC sC)
    {
        if (arr == null || arr.length == 0) {
            return -1;
        }
  
        if (arr.length == 1) { // just eliminate case of length==1
  
            // since algorithm needs min array size==2
            // to start final evaluations
            if (arr[0] == key) {
                return 0;
            }
            if (arr[0] < key && sC == SC.EQUAL_OR_SMALLER) {
                return 0;
            }
            if (arr[0] > key && sC == SC.EQUAL_OR_BIGGER) {
                return 0;
            }
            return -1;
        }
        return searchEqualOrClose(arr, key, 0, arr.length - 1, sC);
    }
  
    private static int searchEqualOrClose(int[] arr, int key,
                                          int start, int end, SC sC)
    {
        int midPos = (start + end) / 2;
        int midVal = arr[midPos];
        if (midVal == key) {
            return midPos; // equal is top priority
        }
  
        if (start >= end - 1) {
            if (arr[end] == key) {
                return end;
            }
            if (sC == SC.EQUAL_OR_SMALLER) {
  
                // find biggest of smaller element
                if (arr[start] > key && start != 0) {
  
                    // even before if "start" is not a first
                    return start - 1;
                }
                if (arr[end] < key) {
                    return end;
                }
                if (arr[start] < key) {
                    return start;
                }
                return -1;
            }
            if (sC == SC.EQUAL_OR_BIGGER) {
  
                // find smallest of bigger element
                if (arr[end] < key && end != arr.length - 1) {
  
                    // even after if "end" is not a last
                    return end + 1;
                }
                if (arr[start] > key) {
                    return start;
                }
                if (arr[end] > key) {
                    return end;
                }
                return -1;
            }
            return -1;
        }
        if (midVal > key) {
            return searchEqualOrClose(arr, key, start, midPos - 1, sC);
        }
        return searchEqualOrClose(arr, key, midPos + 1, end, sC);
    }
  
    public static void main(String[] args)
    {
        int[] arr = new int[] { 0, 2, 4, 6 };
  
        // test full range of xs and SearchCriteria
        for (int x = -1; x <= 7; x++) {
            int pos = searchEqualOrClose(x, arr, SC.EQUAL);
            printResult(x, pos, SC.EQUAL);
            pos = searchEqualOrClose(x, arr, SC.EQUAL_OR_SMALLER);
            printResult(x, pos, SC.EQUAL_OR_SMALLER);
            pos = searchEqualOrClose(x, arr, SC.EQUAL_OR_BIGGER);
            printResult(x, pos, SC.EQUAL_OR_BIGGER);
        }
    }
}
输出:
-1, EQUAL:-1
-1, EQUAL_OR_SMALLER:-1
-1, EQUAL_OR_BIGGER:0
0, EQUAL:0
0, EQUAL_OR_SMALLER:0
0, EQUAL_OR_BIGGER:0
1, EQUAL:-1
1, EQUAL_OR_SMALLER:0
1, EQUAL_OR_BIGGER:1
2, EQUAL:1
2, EQUAL_OR_SMALLER:1
2, EQUAL_OR_BIGGER:1
3, EQUAL:-1
3, EQUAL_OR_SMALLER:1
3, EQUAL_OR_BIGGER:2
4, EQUAL:2
4, EQUAL_OR_SMALLER:2
4, EQUAL_OR_BIGGER:2
5, EQUAL:-1
5, EQUAL_OR_SMALLER:2
5, EQUAL_OR_BIGGER:3
6, EQUAL:3
6, EQUAL_OR_SMALLER:3
6, EQUAL_OR_BIGGER:3
7, EQUAL:-1
7, EQUAL_OR_SMALLER:3
7, EQUAL_OR_BIGGER:-1

时间复杂度:O(log n)