算法——二分查找

二分查找

前置知识:无

定义:他利用数据的有序性,每轮缩小一半的搜索范围,直到找到目标元素或搜索区间为空为止。

基本思想:在有序列表中,每次都取中间值作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若其小于中间值,则在中间值以左进行查找;反之,在中间值以右进行查找。不断重复上面的过程,直到找到目标元素或搜索区间为空为止。


二分查找的几种情况分析

  1. 有序数组中确定num值是否存在
    public static int binarySearch(int[] arr, int target){
        int l = 0;
        int r = arr.length - 1;
        int m = 0;
        while(l <= r){
            m = (l + r) / 2;
            if(arr[m] < target){
                l = m + 1;
            }
            if(arr[m] > target){
                r = m -1;
            }
            else {
                return m;
            }
        }
        return -1;
    }

2.在有序数组中找>=num的最左位置

    public static int findLeft(int[] arr, int target) {
        int l = 0, r = arr.length - 1;
        int ans = -1;
        while(l <= r) {
            int m = (l + r) / 2;
            if(arr[m] < target) {
                l = m + 1;
            }else {
                ans = m;
                r = m - 1;
            }
        }
        return ans;
    }

3.在有序数组中找<=num的最右位置

    public static int findRight(int[] arr, int target) {
        int l = 0, r = arr.length - 1;
        int ans = -1;
        while(l <= r) {
            int m = (l + r) / 2;
            if(arr[m] > target){
                r = m - 1;
            } else {
                ans = m;
                l = m + 1;
            }
        }
        return ans;
    }

二分之美~!

你真的理解二分吗???

题目2:https://leetcode.cn/problems/nth-magical-number/description/

package class002;

/**
 * ClassName: Code02_NthMagicalNumber
 * Package: class002
 * Description:
 *
 * @Author 华因斯坦
 * @Create 2025/4/17 8:40
 * @Version 1.0
 */
public class Code02_NthMagicalNumber {

    public static long gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

    public static long lcm(int a, int b) {
        return a / gcd(a, b) * b;
    }

    public static int nthMagicalNumber(int n, int a, int b) {
        long lcm = lcm(a, b);
        long l = 0, r = (long)n * Math.min(a, b);
        long mid = 0;
        long ans = 0;
        while(l <= r) {
            mid = l + ((r - l) >> 1);
            if(mid / a + mid / b - mid / lcm >= n) {
                ans = mid;
                l = mid + 1;
            }else {
                r = mid -1;
            }
        }
        return (int)(ans % 1000000007);
    }

    public static void main(String[] args) {
        int n = 4, a = 2, b = 3;
        System.out.println(nthMagicalNumber(n, a, b));

    }

}

难道二分查找只能在有序数组中出现吗???

题目2:https://leetcode.cn/problems/find-peak-element/

package class002;

/**
 * ClassName: FindPeakElement
 * Package: class002
 * Description:
 *
 * @Author 华因斯坦
 * @Create 2025/4/16 21:50
 * @Version 1.0
 */
// |--->法一(自己写的):
public class FindPeakElement {
    public static int findPeakElement(int[] nums) {
        if(nums.length == 1) return 0;
        int l = 0, r = nums.length - 1;
        int mid = 0;
        if(nums[l] > nums[l + 1]) return l;
        if(nums[r] > nums[r - 1]) return r;
        while(l <= r) {
            mid = l + ((r - l) >> 1);
            if(mid == 0) {
                mid = 1;
            } else if (mid == nums.length - 1) {
                mid = nums.length - 2;
            }
            if(nums[mid] > nums[mid - 1]){
                if(nums[mid] > nums[mid + 1]){
                    return mid;
                }else{
                    l = mid + 1;
                    continue;
                }
            } else {
                r = mid - 1;
            }
        }
        return -1;
    }
}


// |--->法二(大神写的):

public class FindPeakElement {
    public static int findPeakElement(int[] arr) {
        int n = arr.length;
        if (arr.length == 1) {
            return 0;
        }
        if (arr[0] > arr[1]) {
            return 0;
        }
        if (arr[n - 1] > arr[n - 2]) {
            return n - 1;
        }
        // 这里与我写的不同,但是比我更好(慢慢体会,慢慢从题目中去分析吧)
        int l = 1, r = n - 2, m = 0, ans = -1;
        while (l <= r) {
            m = (l + r) / 2;
            if (arr[m - 1] > arr[m]) {
                r = m - 1;
            } else if (arr[m] < arr[m + 1]) {
                l = m + 1;
            } else {
                ans = m;
                break;
            }
        }
        return ans;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值