【done】剑指offer53:在排序数组中查找数字

力扣,https://leetcode.cn/problems/zai-pai-xu-shu-zu-zhong-cha-zhao-shu-zi-lcof/description/
二分查找,边界问题

solution1,二分搜索目标值 + 线性扫描

递归版二分搜索,其实不太好

class Solution {
    public int countTarget(int[] scores, int target) {
        if (scores.length == 0) {
            return 0;
        }
        int[] inxArray = new int[]{-1, -1};
        binarySearch(0, scores.length - 1, scores, target, inxArray);
        if (inxArray[0] == -1 && inxArray[1] == -1) {
            return 0;
        }
        return inxArray[1] - inxArray[0] + 1;
    }

    // 递归版二分搜索
    public void binarySearch(int start, int end, int[] scores, int target, int[] inxArray) {
        if (start > end) {
            return;
        }

        int mid = start + (end - start) / 2;
        if (scores[mid] == target) {
            inxArray[0] = mid;
            inxArray[1] = mid;
            while (inxArray[0] - 1 >= 0 && scores[inxArray[0] - 1] == target) {
                inxArray[0] -= 1;
            }
            while (inxArray[1] + 1 < scores.length && scores[inxArray[1] + 1] == target) {
                inxArray[1] += 1;
            }
            return;
        } else if (scores[mid] < target) {
            start = mid + 1;
            binarySearch(start, end, scores, target, inxArray);
        } else {
            end = mid - 1;
            binarySearch(start, end, scores, target, inxArray);
        }
    }

}

	// 迭代版二分搜索
    public void binarySearch(int start, int end, int[] scores, int target, int[] inxArray) {
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (scores[mid] == target) {
                inxArray[0] = mid;
                inxArray[1] = mid;
                while (inxArray[0] - 1 >= 0 && scores[inxArray[0] - 1] == target) {
                    inxArray[0] -= 1;
                }
                while (inxArray[1] + 1 < scores.length && scores[inxArray[1] + 1] == target) {
                    inxArray[1] += 1;
                }
                return;
            } else if (scores[mid] > target) {
                end = mid - 1;
            } else if (scores[mid] < target) {
                start = mid + 1;
            }
        }
    }

solution2,二分搜索边界索引

值得推荐的做法!!!注意:不必检查边界,写法不必像《算法小抄》中繁琐!考虑两种极限情况:
(1)target > scores[n - 1],则左侧索引返回n,右侧索引返回n - 1,最终答案 = (n - 1) - n + 1 = 0;
(2)target < scores[0],则左侧索引返回0,右侧索引返回-1,最终答案 = - 1 - 0 + 1 = 0;
所以最终答案可以非常简洁!!!

class Solution {
    public int countTarget(int[] scores, int target) {
        if (scores.length == 0) {
            return 0;
        }
        int leftIndex = leftBoundSearch(0, scores.length - 1, scores, target);
        int rightIndex = rightBoundSearch(0, scores.length - 1, scores, target);
        
        return rightIndex - leftIndex + 1;
    }

    public int leftBoundSearch(int start, int end, int[] scores, int target) {
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (scores[mid] == target) {
                end = mid - 1;
            } else if (scores[mid] > target) {
                end = mid - 1;
            } else if (scores[mid] < target) {
                start = mid + 1;
            }
        }

        return start;
    }

    public int rightBoundSearch(int start, int end, int[] scores, int target) {
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (scores[mid] == target) {
                start = mid + 1;
            } else if (scores[mid] > target) {
                end = mid - 1;
            } else if (scores[mid] < target) {
                start = mid + 1;
            }
        }

        return end;
    }
}

你可能感兴趣的:(剑指offer题目笔记,二分查找)