二分查找(變體)代碼框架 1.說明 2.查找正好大於target的元素 3.查找正好小於target的元素 4.二分查找(變體)代碼框架優化

1.說明

前面介紹了二分查找代碼框架,
查找的都是與target相同的數,
本文介紹的二分查找變體,
查找的是正好大於或者小於target的數,
即要找的數target不存在,
希望返回滿足一定要求的數。

2.查找正好大於target的元素

這是二分查找代碼框架中,
查找左側邊界代碼框架的變體,
當target不存在時,
得到的索引恰好是比target大的最小元素的索引,
即nums數組中第1個大於target的元素索引。

public static int leftBound(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;
    // 下面的兩個判斷可省略,最終結果會覆蓋這兩種情況
    // target比最小的元素還小,那索引爲0的元素正好比target大
    if (target < nums[left]) {
        return 0;
    }
    // target比最大的元素還大,則-1表示沒有比target大的元素了
    if (target > nums[right]) {
        return -1;
    }
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 不能返回,鎖定左邊界,繼續縮小右邊界
            right = mid - 1;
        }
        // 上面的"right = mid - 1;"代碼體相同,
        // 判斷條件可以合併爲else if (nums[mid] >= target)
    }
    return left;
}

3.查找正好小於target的元素

這是二分查找代碼框架中,
查找右側邊界代碼框架的變體,
當target不存在時,
得到的索引恰好是比target小的最大元素的索引,
即nums數組中最後一個小於target的元素索引。

public static int rightBound(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;
    // 下面的兩個判斷可省略,最終結果會覆蓋這兩種情況
    // target比最小的元素還小,則-1表示沒有比target小的元素了
    if (target < nums[left]) {
        return -1;
    }
    // target比最大的元素還大,那索引爲nums.length-1的元素正好比target小
    if (target > nums[right]) {
        return right;
    }
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        } else if (nums[mid] == target) {
            // 不能返回,鎖定右邊界,繼續縮小左邊界
            left = mid + 1;
        }
        // 上面的"left = mid + 1;"代碼體相同,
        // 判斷條件可以合併爲else if (nums[mid] <= target)
    }
    return right;
}

4.二分查找(變體)代碼框架優化

如下代碼優化後非常簡潔,
適合在實際項目中使用,
但是不推薦記憶下面的代碼框架,
因爲合併了很多實現細節,
不利於分析和理解,
還是推薦記憶上面的原始版本。

4.1.查找左側邊界變體優化

public static int leftBoundAdvance(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] < target) {
         left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return left;
}

4.2.查找右側邊界變體優化

public static int rightBoundAdvnce(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] <= target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return right;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章