Skip to content

二分查找

二分搜索(Binary Search)是一种在有序数组或列表中查找目标值的高效算法,其时间复杂度是 O(log n)。以下是一些经典的二分搜索题目及其示例:

1. 二分查找:查找目标值

题目描述: 给定一个升序排序的数组 nums 和一个目标值 target,请在数组中查找目标值的位置。如果目标值存在,则返回其索引;如果目标值不存在,则返回 -1。

示例代码(Kotlin):

kotlin
fun binarySearch(nums: IntArray, target: Int): Int {
    var left = 0
    var right = nums.size - 1
    while (left <= right) {
        val mid = left + (right - left) / 2
        if (nums[mid] == target) {
            return mid  // 找到目标值,返回索引
        } else if (nums[mid] < target) {
            left = mid + 1  // 目标值在右半部分
        } else {
            right = mid - 1  // 目标值在左半部分
        }
    }
    return -1  // 目标值不存在
}

fun main() {
    val nums = intArrayOf(1, 3, 5, 7, 9)
    println(binarySearch(nums, 5))  // 输出: 2
    println(binarySearch(nums, 8))  // 输出: -1
}

2. 寻找旋转排序数组中的最小值

题目描述: 给定一个已经升序排序的数组,但是该数组经过旋转,求旋转数组中的最小值。

示例代码(Kotlin):

kotlin
fun findMin(nums: IntArray): Int {
    var left = 0
    var right = nums.size - 1
    while (left < right) {
        val mid = left + (right - left) / 2
        if (nums[mid] > nums[right]) {
            left = mid + 1  // 最小值在右半部分
        } else {
            right = mid  // 最小值在左半部分
        }
    }
    return nums[left]  // left 就是最小值的索引
}

fun main() {
    val nums = intArrayOf(4, 5, 6, 7, 0, 1, 2)
    println(findMin(nums))  // 输出: 0
}

3. 寻找一个元素在有序数组中的位置(变种)

题目描述: 在一个升序排序的数组 nums 中,寻找目标值 target 的插入位置(即使目标值不存在,也应该返回目标值应当插入的位置)。

示例代码(Kotlin):

kotlin
fun searchInsert(nums: IntArray, target: Int): Int {
    var left = 0
    var right = nums.size
    while (left < right) {
        val mid = left + (right - left) / 2
        if (nums[mid] < target) {
            left = mid + 1  // 目标值在右半部分
        } else {
            right = mid  // 目标值在左半部分
        }
    }
    return left  // left 是目标值的插入位置
}

fun main() {
    val nums = intArrayOf(1, 3, 5, 6)
    println(searchInsert(nums, 5))  // 输出: 2
    println(searchInsert(nums, 2))  // 输出: 1
    println(searchInsert(nums, 7))  // 输出: 4
}

4. 查找旋转数组中的最大值

题目描述: 给定一个旋转的升序数组,找到该数组中的最大值。

示例代码(Kotlin):

kotlin
fun findMax(nums: IntArray): Int {
    var left = 0
    var right = nums.size - 1
    while (left < right) {
        val mid = left + (right - left) / 2
        if (nums[mid] > nums[right]) {
            left = mid + 1  // 最大值在左半部分
        } else {
            right = mid  // 最大值在右半部分
        }
    }
    return nums[left - 1]  // left 是最小值的索引,最大值在其左侧
}

fun main() {
    val nums = intArrayOf(4, 5, 6, 7, 0, 1, 2)
    println(findMax(nums))  // 输出: 7
}

5. 平方根的二分查找

题目描述: 给定一个非负整数 x,返回 x 的平方根(结果只保留整数部分,即向下取整)。

示例代码(Kotlin):

kotlin
fun mySqrt(x: Int): Int {
    var left = 0
    var right = x
    while (left <= right) {
        val mid = left + (right - left) / 2
        if (mid * mid == x) {
            return mid  // 找到精确平方根
        } else if (mid * mid < x) {
            left = mid + 1
        } else {
            right = mid - 1
        }
    }
    return right  // 返回最大的整数平方根
}

fun main() {
    println(mySqrt(8))  // 输出: 2
    println(mySqrt(16))  // 输出: 4
}

6. 寻找一个数的第一个和最后一个位置

题目描述: 给定一个升序排序的数组 nums 和一个目标值 target,找出目标值在数组中的第一个和最后一个位置。如果目标值不存在,返回 [-1, -1]。

示例代码(Kotlin):

kotlin
fun searchRange(nums: IntArray, target: Int): IntArray {
    fun findFirst(): Int {
        var left = 0
        var right = nums.size
        while (left < right) {
            val mid = left + (right - left) / 2
            if (nums[mid] < target) {
                left = mid + 1
            } else {
                right = mid
            }
        }
        return if (left < nums.size && nums[left] == target) left else -1
    }

    fun findLast(): Int {
        var left = 0
        var right = nums.size
        while (left < right) {
            val mid = left + (right - left) / 2
            if (nums[mid] <= target) {
                left = mid + 1
            } else {
                right = mid
            }
        }
        return if (left > 0 && nums[left - 1] == target) left - 1 else -1
    }

    val first = findFirst()
    return if (first == -1) {
        intArrayOf(-1, -1)
    } else {
        intArrayOf(first, findLast())
    }
}

fun main() {
    val nums = intArrayOf(5, 7, 7, 8, 8, 10)
    println(searchRange(nums, 8).joinToString())  // 输出: 3, 4
}

Released under the MIT License.