深入理解二分查找算法及其在 Java 中的实现

4 篇文章 0 订阅

深入理解二分查找算法及其在 Java 中的实现

在计算机科学中,二分查找(Binary Search)是一种在有序数组中查找某一特定元素的搜索算法。这种算法每次将查找区间减半,从而大大减少了查找时间,时间复杂度为 O(log n)。二分查找是一种非常高效的查找算法,广泛应用于各种软件系统中。本文将深入探讨二分查找算法的原理、步骤、实现方式以及应用场景。

二分查找算法的原理

二分查找算法的基本思想是:在有序数组中,通过比较目标值与数组中间元素的大小,每次将查找区间缩小一半,直到找到目标值或确定目标值不存在于数组中。

前提条件

二分查找算法的前提条件是数组必须是有序的。如果数组无序,需要先对数组进行排序。

基本步骤

  1. 初始化:设定查找区间的起始位置 low 和结束位置 high,通常初始值为 low = 0high = array.length - 1
  2. 计算中间位置:计算中间位置 mid,公式为 mid = low + (high - low) / 2
  3. 比较目标值与中间元素
    • 如果目标值等于中间元素,返回中间元素的索引。
    • 如果目标值小于中间元素,将查找区间缩小到左半部分,即 high = mid - 1
    • 如果目标值大于中间元素,将查找区间缩小到右半部分,即 low = mid + 1
  4. 重复步骤 2 和 3,直到找到目标值或查找区间为空(即 low > high)。

二分查找算法的实现

递归实现

递归实现是二分查找算法的一种常见实现方式。递归实现的代码简洁,但可能会产生额外的栈空间开销。

public class BinarySearch {
    public static int binarySearchRecursive(int[] array, int target) {
        return binarySearchRecursive(array, target, 0, array.length - 1);
    }

    private static int binarySearchRecursive(int[] array, int target, int low, int high) {
        if (low > high) {
            return -1; // 目标值不存在
        }

        int mid = low + (high - low) / 2;
        if (array[mid] == target) {
            return mid; // 找到目标值
        } else if (array[mid] > target) {
            return binarySearchRecursive(array, target, low, mid - 1); // 在左半部分查找
        } else {
            return binarySearchRecursive(array, target, mid + 1, high); // 在右半部分查找
        }
    }

    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int target = 7;
        int result = binarySearchRecursive(array, target);
        if (result != -1) {
            System.out.println("Element found at index: " + result);
        } else {
            System.out.println("Element not found");
        }
    }
}

迭代实现

迭代实现是二分查找算法的另一种常见实现方式。迭代实现的代码稍微复杂一些,但不会产生额外的栈空间开销。

public class BinarySearch {
    public static int binarySearchIterative(int[] array, int target) {
        int low = 0;
        int high = array.length - 1;

        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (array[mid] == target) {
                return mid; // 找到目标值
            } else if (array[mid] > target) {
                high = mid - 1; // 在左半部分查找
            } else {
                low = mid + 1; // 在右半部分查找
            }
        }

        return -1; // 目标值不存在
    }

    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int target = 7;
        int result = binarySearchIterative(array, target);
        if (result != -1) {
            System.out.println("Element found at index: " + result);
        } else {
            System.out.println("Element not found");
        }
    }
}

二分查找算法的优化

防止整数溢出

在计算中间位置 mid 时,使用 mid = low + (high - low) / 2 而不是 mid = (low + high) / 2,可以防止整数溢出问题。

处理重复元素

在实际应用中,数组中可能存在重复元素。如果需要查找第一个或最后一个等于目标值的元素,可以在找到目标值后继续在左半部分或右半部分查找。

查找第一个等于目标值的元素
public class BinarySearch {
    public static int binarySearchFirstOccurrence(int[] array, int target) {
        int low = 0;
        int high = array.length - 1;
        int result = -1;

        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (array[mid] == target) {
                result = mid; // 记录当前找到的位置
                high = mid - 1; // 继续在左半部分查找
            } else if (array[mid] > target) {
                high = mid - 1; // 在左半部分查找
            } else {
                low = mid + 1; // 在右半部分查找
            }
        }

        return result; // 返回第一个等于目标值的元素索引
    }

    public static void main(String[] args) {
        int[] array = {1, 2, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10};
        int target = 3;
        int result = binarySearchFirstOccurrence(array, target);
        if (result != -1) {
            System.out.println("First occurrence of element found at index: " + result);
        } else {
            System.out.println("Element not found");
        }
    }
}
查找最后一个等于目标值的元素
public class BinarySearch {
    public static int binarySearchLastOccurrence(int[] array, int target) {
        int low = 0;
        int high = array.length - 1;
        int result = -1;

        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (array[mid] == target) {
                result = mid; // 记录当前找到的位置
                low = mid + 1; // 继续在右半部分查找
            } else if (array[mid] > target) {
                high = mid - 1; // 在左半部分查找
            } else {
                low = mid + 1; // 在右半部分查找
            }
        }

        return result; // 返回最后一个等于目标值的元素索引
    }

    public static void main(String[] args) {
        int[] array = {1, 2, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10};
        int target = 3;
        int result = binarySearchLastOccurrence(array, target);
        if (result != -1) {
            System.out.println("Last occurrence of element found at index: " + result);
        } else {
            System.out.println("Element not found");
        }
    }
}

二分查找算法的应用场景

查找元素

二分查找算法最常见的应用场景是在有序数组中查找某一特定元素。例如,在一个有序的学生成绩数组中查找某个学生的成绩。

查找插入位置

在某些情况下,需要在有序数组中插入一个新元素,并保持数组有序。可以使用二分查找算法找到插入位置,然后进行插入操作。

public class BinarySearch {
    public static int binarySearchInsertPosition(int[] array, int target) {
        int low = 0;
        int high = array.length - 1;

        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (array[mid] == target) {
                return mid; // 找到目标值,返回索引
            } else if (array[mid] > target) {
                high = mid - 1; // 在左半部分查找
            } else {
                low = mid + 1; // 在右半部分查找
            }
        }

        return low; // 返回插入位置
    }

    public static void main(String[] args) {
        int[] array = {1, 2, 4, 5, 6, 7, 8, 9, 10};
        int target = 3;
        int insertPosition = binarySearchInsertPosition(array, target);
        System.out.println("Insert position for element: " + insertPosition);
    }
}

查找旋转排序数组中的元素

在某些情况下,数组可能经过旋转,但仍然部分有序。可以使用二分查找算法在旋转排序数组中查找元素。

public class BinarySearch {
    public static int binarySearchRotatedArray(int[] array, int target) {
        int low = 0;
        int high = array.length - 1;

        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (array[mid] == target) {
                return mid; // 找到目标值,返回索引
            }

            if (array[low] <= array[mid]) { // 左半部分有序
                if (array[low] <= target && target < array[mid]) {
                    high = mid - 1; // 在左半部分查找
                } else {
                    low = mid + 1; // 在右半部分查找
                }
            } else { // 右半部分有序
                if (array[mid] < target && target <= array[high]) {
                    low = mid + 1; // 在右半部分查找
                } else {
                    high = mid - 1; // 在左半部分查找
                }
            }
        }

        return -1; // 目标值不存在
    }

    public static void main(String[] args) {
        int[] array = {4, 5, 6, 7, 0, 1, 2};
        int target = 0;
        int result = binarySearchRotatedArray(array, target);
        if (result != -1) {
            System.out.println("Element found at index: " + result);
        } else {
            System.out.println("Element not found");
        }
    }
}

总结

二分查找算法是一种高效的查找算法,适用于在有序数组中查找某一特定元素。通过每次将查找区间减半,二分查找算法的时间复杂度为 O(log n),远优于线性查找的 O(n)。本文详细介绍了二分查找算法的原理、步骤、实现方式以及应用场景,并提供了递归和迭代两种实现方式的代码示例。此外,还讨论了二分查找算法的优化方法,如防止整数溢出和处理重复元素。希望这篇博客能帮助你更好地理解和应用二分查找算法,提升你的编程能力。

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

需要重新演唱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值