二分查找常見變種方法的代碼實現

二分查找變種:

1. 查找大於target的所有值的最小索引;

2. 查找等於target的所有值的最大索引(上界);

3. 查找大於target的所有值的最大索引;

 

代碼示例:

/**
 * 二分查找工具對象
 */
const BinarySearch = (function() {
    return {
        /**
         * 找出大於target的所有值中的最小索引
         * @param {number[]} nums - 有序數組
         * @param {number} target - 目標值
         */
        upper(nums, target) {
            let l = 0;
            let r = nums.length;
            // 在[l, r) 範圍內查找target
            while (l < r) {
                // 中位數索引
                const m = l + Math.floor((r - l) / 2);
                // 如果m位置上的值比target小或者相等,則將左指針l移動至m + 1
                if (nums[m] <= target) {
                    l = m + 1;
                }
                // 如果當前位置上的值比target大,則移動r至m
                else {
                    r = m;
                }
            }

            return l;
        },
        /**
         * 找出等於target的值的最大索引(如果沒有等於target的值,則返回大於target的值中的最小索引)
         * @param {number[]} nums - 有序數組
         * @param {number} target - 目標值
         */
        ceil(nums, target) {
            // 先找出大於target元素的最小值的索引
            const upper_idx = this.upper(nums, target);
            // 如果該索引的前一個位置上的值正好等於target,返回該值
            if (upper_idx > 0 && nums[upper_idx - 1] === target) {
                return upper_idx - 1;
            }
            // 否則返回比大於target的值中的最小索引
            return upper_idx;
        },
        /**
         * 找出小於target的所有值中的最小索引
         * @param nums 
         * @param target 
         */
        lower(nums, target) {
            let l = 0;
            let r = nums.length - 1;
            // 在[l, r)範圍內搜索
            while (l < r) {
                // 相對於upper函數,這裏m的取值調整爲“上取整”(避免l留在原地,造成死循環 )
                const m = l + Math.ceil((r - l) / 2);
                // 當前值小於target,可能符合調整,所以將l指針調整m
                if (nums[m] < target) {
                    l = m;
                }
                // 如果大於等於target(不合符搜索目標),將r調整到m - 1
                else {
                    r = m - 1;
                }
            }

            return l;
        },
    };
})();

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章