行列有序矩阵搜索[二分 && Z字搜索]

文章介绍了如何在行列有序的二维矩阵中高效搜索目标元素。从最基础的暴力遍历O(mn),到利用二分搜索和剪枝策略降低到O(mlogn),再到Z字压缩方法实现O(m+n)的时间复杂度。通过逐步优化算法,展示了在处理这类问题时如何利用规律和转换问题来提升效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

从矩阵中搜索一个元素,暴力搜索O(mn)。如果行列有序,则可二分 + 剪枝来进行搜索。除此之外,利用行列同时有序,在搜索的过程中将可搜索空间压缩,直至找到target,为Z字搜索O(m + n)。

一、搜索二维矩阵

在这里插入图片描述

二、二分 & Z字压缩

1、idea

a.暴力,通过行列遍历,寻找target,O(mn);
b.保持有序对二分的紧密联系,每行通过二分搜索,再利用列的有序性进行剪枝
c.Z字压缩,同时利用行列有序,对可搜索空间进行逐行逐列进行压缩,寻找target。

2、二分 + 剪枝

func searchMatrix(matrix [][]int, target int) bool {
    // 每行进行搜索
    for i := 0;i < len(matrix);i++ {
        // 剪枝,当最小值都大于target,就没必要搜索了。
        if matrix[i][0] > target {
            return false
        }
        // 二分查找
        if binarySearch(matrix[i],target) {
            return true
        }
    }
    return false
}
// 二分搜索
func binarySearch(nums []int,target int) bool {
    low,high := 0,len(nums) - 1
    for low <= high {
        mid := low + (high - low) >> 1
        midVal := nums[mid]

        if target == midVal {
            return true
        }
        if target < midVal {
            high = mid - 1
        }else {
            low = mid + 1
        }
    }
    return false
}
// 搜索矩阵中是否有元素值为target
// 行列升序,必不可能暴力搜索。
// 针对每行,进行二分查找,可降低时间复杂度至mlogn

3、Z字压缩

// 方法二:Z字搜索
// 充分利用行列有序,对搜索空间逐渐压缩,O(m + n)。
// 根据右上角的值val情况,当val > target,说明最后一列的所有值都大于target,则压缩一列;反之,第一列都小于target,则压缩一行。
func searchMatrix(matrix [][]int, target int) bool {
    x,y := 0,len(matrix[0]) - 1
    bx,by := len(matrix) - 1,0

    for ; x <= bx && y >= by; {
        // 找到target
        if matrix[x][y] == target {
            return true
        }
        // val > target,压缩一列。
        if matrix[x][y] > target {
            y--
        }else { // 压缩一行
            x++
        }
    }
    return false
}

总结

1)从不利用规律的暴力法,到利用规律的二分 + 剪枝法,再到更充分利用规律进行问题转换的Z字搜索法,挖掘规律,问题/逻辑转换,不断降低时空复杂度。
2)保持有序对二分的紧密联系。

参考文献

[1] LeetCode 行列有序矩阵搜索
[2] LeetCode 官方解答 Z字搜索

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值