[M模拟] lc2711. 对角线上不同值的数量差(对角线遍历+前后缀分解)

1. 题目来源

链接:2711. 对角线上不同值的数量差

前置题:

题单:

  • 待补充

2. 题目解析

2025年03月25日21:21:28

方法一:暴力

  • 由于这个题目数据量太小了哈,就完全可以暴力来做,每次去暴力判断下左上侧、右下侧对角线的重复元素个数即可。

方法二:前后缀分解

  • 暴力显然在同一个对角线上有很多元素被重复遍历。
  • 这个时候就需要对角线的前后缀分解。确保重复遍历次数较少。
    • 直接遍历每一条对角线元素。
    • 从左上方到右下方这样的遍历方向。
    • 同时统计左上方对角线的不同元素个数。作为前缀统计,直接放到答案中。
    • 再从右下方到左上方这样的遍历方向。
    • 此时就可以直接计算答案了,同时统计 右下方 到 左上方 对角线的不同元素个数。作为后缀统计,直接与前缀元素计算答案即可。
  • 所以,每个元素至多被遍历两遍。

方法三:状态压缩+前后缀分解

  • 这个没啥难度哈,一个简单的状态压缩,将 set 使用一个 uint64 的数字进行代替,是完全可以的哈。
  • 注意里面一些位运算的 API 和技巧 即可。

  • 时间复杂度 O ( n m ) O(nm) O(nm)
  • 空间复杂度 O ( 1 ) O(1) O(1) 返回值不计算

方法二:前后缀分解

func differenceOfDistinctValues(grid [][]int) [][]int {
    n, m := len(grid), len(grid[0])
    res := make([][]int, n)
    for i := range n {
        res[i] = make([]int, m)
    }
    set := map[int]struct{}{}
    for k := 1; k < n + m; k ++ {
        minJ, maxJ := max(0, m - k), min(m - 1, n - 1 - k + m)
        
        clear(set)        
        for j := minJ; j <= maxJ; j ++ {    // 处理前缀
            i := j + k - m
            res[i][j] = len(set)            // 不包含(i, j) 注意顺序
            set[grid[i][j]] = struct{}{}   
        }

        clear(set)
        for j := maxJ; j >= minJ; j -- {   // 处理后缀,计算答案
            i := j + k - m
            res[i][j] = abs(res[i][j] - len(set))
            set[grid[i][j]] = struct{}{}
        }
    }
    
    return res
}

func abs(x int) int { 
    if x < 0 { 
        return -x 
    } 
    return x 
}

方法一:暴力

func differenceOfDistinctValues(grid [][]int) [][]int {
    n, m := len(grid), len(grid[0])
    res := make([][]int, n)
    for i := range n {
        res[i] = make([]int, m)
    }

    getL := func(x, y int) int {
        s := map[int]struct{}{}
        x -- 
        y -- 
        for x >= 0 && y >= 0 {
            s[grid[x][y]] = struct{}{}
            x --
            y --
        }

        return len(s)
    }

    getR := func(x, y int) int {
        s := map[int]struct{}{}
        x ++ 
        y ++ 
        for x < n && y < m {
            s[grid[x][y]] = struct{}{}
            x ++
            y ++
        }

        return len(s)
    }
    abs := func(x int) int {
        if x > 0 {
            return x
        }

        return -x
    }

    for i := range n {
        for j := range m {
            res[i][j] = abs(getL(i, j) - getR(i, j))
        }
    }

    return res
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

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

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

打赏作者

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

抵扣说明:

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

余额充值