返回

用Python 精妙破解LeetCode 378:探寻有序矩阵中的第K小元素

闲谈

欢迎踏入有序矩阵的奥秘世界,我们将一同探索如何在LeetCode 378中寻找第K小元素。沿途,您将领略从暴力解法到二分查找法的算法演进,充分感受算法的魅力和效率之美。

一、暴力解法:直接排序,轻松直达答案

最朴素的解法莫过于将矩阵的所有元素提取出来,组成一个数组,然后对数组进行排序,最后返回第K个元素。这种方法简单粗暴,但计算量过大,时间复杂度为O(n^2logn)。

def find_kth_smallest(matrix, k):
    # 将矩阵展开成数组
    arr = []
    for row in matrix:
        arr.extend(row)

    # 对数组进行排序
    arr.sort()

    # 返回第K个元素
    return arr[k-1]

二、二分查找:巧妙运用矩阵特性,大幅提升效率

若细究矩阵的特性,您会发现每行和每列都是有序的。因此,我们可以利用二分查找法来缩小搜索范围,大幅提高算法的效率。时间复杂度降至O(nlogn),大大降低计算成本。

原理解析

在有序矩阵中,每一行和每一列都是递增的。这意味着,如果我们能确定某个值的位置,就可以通过它来确定其他位置的值。例如,如果我们找到一个中间值mid,那么我们可以统计出有多少个元素小于等于这个mid。根据这个数量与k的关系,我们可以调整搜索范围,从而逐步逼近第K小的元素。

代码实现

import bisect

def find_kth_smallest(matrix, k):
    # 二分查找的目标值
    target = k

    # 确定矩阵的行数和列数
    rows, cols = len(matrix), len(matrix[0])

    # 二分查找的左右边界
    left, right = matrix[0][0], matrix[rows-1][cols-1]

    # 在左右边界之间进行二分查找
    while left <= right:
        # 计算中间值
        mid = (left + right) // 2

        # 统计小于等于中间值的元素个数
        count = 0
        for row in matrix:
            index = bisect.bisect_left(row, mid)
            count += index

        # 如果小于等于中间值的元素个数小于K,则将左边界更新为中间值加1
        if count < target:
            left = mid + 1

        # 如果小于等于中间值的元素个数大于等于K,则将右边界更新为中间值减1
        else:
            right = mid - 1

    # 返回第K小的元素
    return left

三、结语:探索算法奥秘,领略编程艺术

LeetCode 378 中寻找有序矩阵的第K小元素之旅已圆满结束。我们从暴力解法开始,逐步升级至二分查找法,见证了算法从低效到高效的演变。在这个过程中,您不仅领略了算法的精妙之处,更对Python编程语言有了更深刻的认识。

未来,在探索算法与编程世界的道路上,愿您继续勇往直前,不断创造属于自己的编程传奇!