LeetCode中使用二分查找法的题目的整理(待更)

二分查找(simple难度)

https://leetcode-cn.com/problems/binary-search/

class Solution {
    public int binarySearch(int[] nums, int target) {
        int len = nums.length;
        int left = 0;
        int right = len - 1;//注意,左闭右闭区间,所以right = len - 1
        // 目标元素可能在 左闭右闭 区间:[left, right],但下面while循环是 < 而不是 <= ,要注意
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target) {
                // 下一轮搜索区间是 [mid + 1, right],索引mid对应元素一定不符合要求,所以左边界是mid+1
                left = mid + 1;
            } else {
                // 下一轮搜索区间是 [left, mid],索引mid对应元素可能不符合要求,所以右边界是mid
                right = mid;
            }
        }

        if (nums[left] == target) {
            return left;
        }
        return -1;
    }
}

或者:

class Solution {
    public int binarySearch(int[] nums, int target) {
        int len = nums.length;
        int left = 0;
        int right = len - 1;
        // 定义target在 左闭右闭 的区间里,[left, right]
        //若if (nums[mid] == target) 在while内判断,则是left <= right
        //若不在while内判断相等时的情况,则是left < right
        while (left <= right) {// 当left==right,区间[left, right]依然有效
            int mid = left + (right - left) / 2;    //防止溢出,等同于(left + right)/2
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                //因为target要在左闭右闭的区间里,因为nums[mid]不满足条件,
                //所以要把mid从区间里剔除,所以搜索区间变为[mid + 1, right]
                left = mid + 1; // target在右区间,所以[mid + 1, right]
            } else {
                right = mid - 1;    // target在左区间,所以[left, mid - 1]
            }
        }
        return -1;
    }
}

第一个错误的版本(simple难度)

https://leetcode-cn.com/problems/first-bad-version/

/* The isBadVersion API is defined in the parent class VersionControl.
      boolean isBadVersion(int version); */

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        int left = 1;
        int right = n;
        while (left < right){
            int mid = left + (right - left) / 2;
            if(isBadVersion(mid) == false){
                left = mid + 1;
            }else{
                right = mid;
            }
        }
        return left;
    }
}

猜数字大小(simple难度)

https://leetcode-cn.com/problems/guess-number-higher-or-lower/

/** 
 * Forward declaration of guess API.
 * @param  num   your guess
 * @return 	     -1 if num is lower than the guess number
 *			      1 if num is higher than the guess number
 *               otherwise return 0
 * int guess(int num);
 */

public class Solution extends GuessGame {
    public int guessNumber(int n) {
        int left = 1;
        int right = n;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if(guess(mid) == 0){
                return mid;
            }else if(guess(mid) == -1){
                right = mid - 1;
            }else{
                left = mid + 1;
            }
        }
        return left; 
    }
}

排列硬币(simple难度)

https://leetcode-cn.com/problems/arranging-coins/

排列硬币可以转化成寻找 <=n 的最大等差数列和的尾项。
细节看代码注释。

class Solution {
    public int arrangeCoins(int n) {
        long left = 0;
        long right = n;
        while (left < right) {
            long mid = left + (right - left + 1) / 2;
            //硬币排列类似等差数列求和
            //等差数列求和公式:(首项 + 尾项) * 项数 / 2
            //本题中首项为1,尾项为mid,项数也为mid
            //本题要满足:(首项 + 尾项) * 项数 / 2 <= n
            //整理可得:mid * (mid + 1) <= 2 * n
            if (mid * (mid + 1) > (long) 2 * n) {
                right = mid - 1;
            } else {
                left = mid;
            }
        }
        return (int) left;
    }
}

搜索插入位置(simple难度)

https://leetcode-cn.com/problems/search-insert-position/

class Solution {
    public int searchInsert(int[] nums, int target) {
        int n = nums.length;
        int left = 0;
        int right = n - 1; // 定义target在左闭右闭的区间里,[left, right] 
        while (left <= right) { // 当left==right,区间[left, right]依然有效
            int mid = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[mid] > target) {
                right = mid - 1; // target 在左区间,所以[left, mid - 1]
            } else if (nums[mid] < target) {
                left = mid + 1; // target 在右区间,所以[mid + 1, right]
            } else { // nums[mid] == target
                return mid;
            }
        }
        // 分别处理如下四种情况
        // 目标值在数组所有元素之前  [0, -1]
        // 目标值等于数组中某一个元素  return mid;
        // 目标值插入数组中的位置 [left, right],return  right + 1
        // 目标值在数组所有元素之后的情况 [left, right], return right + 1
        return right + 1;
    }
}

或:

public class Solution {

    public int searchInsert(int[] nums, int target) {
        int len = nums.length;
        if (len == 0) {
            return 0;
        }

        // 特判
        if (nums[len - 1] < target) {
            return len;
        }
        int left = 0;
        int right = len - 1;
        while (left < right) {
            int mid = left + (right - left) / 2;
            // 严格小于 target 的元素一定不是解
            if (nums[mid] < target) {
                // 下一轮搜索区间是 [mid + 1, right]
                left = mid + 1;
            } else {
                // 下一轮搜索区间是 [left, mid]
                right = mid;
            }
        }
        return left;
    }
}

在排序数组中查找元素的第一个和最后一个位置(medium)

https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/

本题方法和代码来源:
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/si-lu-hen-jian-dan-xi-jie-fei-mo-gui-de-er-fen-cha/
来源:力扣(LeetCode)

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int len = nums.length;
        if (len == 0) {
            return new int[]{-1, -1};
        }
		//firstPosition == -1 说明数组中没有target,则返回[-1,-1]
        int firstPosition = findFirstPosition(nums, target);
        if (firstPosition == -1) {
            return new int[]{-1, -1};
        }

        int lastPosition = findLastPosition(nums, target);
        return new int[]{firstPosition, lastPosition};
    }
	//查找相同target值的左边界
    private int findFirstPosition(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) {
                // 下一轮搜索区间是 [mid + 1, right]
                left = mid + 1;
            } else if (nums[mid] == target) {
                // 下一轮搜索区间是 [left, mid],一直向左搜寻,找到左边界
                right = mid;
            } else {
                // nums[mid] > target,下一轮搜索区间是 [left, mid - 1]
                right = mid - 1;
            }
        }

        if (nums[left] == target) {
            return left;
        }
        return -1;
    }
	//查找相同target值的右边界
    private int findLastPosition(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = left + (right - left + 1) / 2;
            if (nums[mid] > target) {
                // 下一轮搜索区间是 [left, mid - 1]
                right = mid - 1;
            } else if (nums[mid] == target){
                // 下一轮搜索区间是 [mid, right],一直向右搜寻,找到右边界
                left = mid;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值