首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >2026-06-28:按位或的最小值。用go语言,给你一个大小为 m × n 的二维整数表 grid。你需要从 每一行 里 各选出一个数(同一行只选一个,

2026-06-28:按位或的最小值。用go语言,给你一个大小为 m × n 的二维整数表 grid。你需要从 每一行 里 各选出一个数(同一行只选一个,

作者头像
福大大架构师每日一题
发布2026-06-29 14:15:19
发布2026-06-29 14:15:19
570
举报

2026-06-28:按位或的最小值。用go语言,给你一个大小为 m × n 的二维整数表 grid。你需要从 每一行 里 各选出一个数(同一行只选一个,不能多选或少选)。把这些被选出的数做按位或运算(bitwise OR)。

你的目标是:让最终得到的 按位或结果尽可能小。返回这个 最小可能的按位或值。

1 <= m == grid.length <= 100000。

1 <= n == grid[i].length <= 100000。

m * n <= 100000。

1 <= grid[i][j] <= 100000。

输入: grid = [[1,5],[2,4]]。

输出: 3。

解释:

从第一行选择 1,从第二行选择 2。

1 | 2 = 3,这是最小可能值。

题目来自力扣3858。

一、代码整体执行分步详细流程

步骤1:先计算所有行最小值的或值 or,确定二进制遍历上限

  1. 1. 遍历每一行,取出该行最小数字;
  2. 2. 将所有行最小值做按位或,得到变量 or
  3. 3. 作用:任何合法选法的或结果,一定 ≤ 这个 or。 原因:每行选最小值时,单个数字本身最小,它们的或自然是一个上界;最终答案的二进制有效位数,不会超过 or 的二进制位数,后续只需要遍历这个范围内的比特位,不用遍历全部32/64位,减少循环次数。 示例: 第一行最小1,第二行最小2,or = 1 | 2 = 3,二进制 11,有效比特位长度为2,只需处理第1位、第0位(从0开始计数)。

步骤2:从最高二进制位往低位逐位贪心判断,构造最小答案ans

初始 ans = 0,从最高位 i = bits.Len(uint(or)) - 1 向下循环到0,每一位执行相同逻辑:

2.1 构造校验掩码 mask

公式:mask = ans | (1<<i - 1) 拆解掩码含义:

  1. 1. ans:已经确定好的高位比特(已经固定不能修改);
  2. 2. 1<<i - 1:第i位以下所有低位全部置1; 整体mask规则:
  • 高于i的位:完全复制当前ans的高位,这部分是已经敲定的、不能改动的比特;
  • 第i位及所有低位:全部为1。

掩码作用:筛选满足「高位和ans完全匹配、第i位可以为0」的候选数字。

2.2 逐行校验:是否每行都存在符合条件的数字

内层遍历每一行,对每行内所有数字x做校验判断 x | mask == mask

  1. 1. 等式逻辑拆解: x | mask = mask 等价于 x & (~mask) = 0 代表x所有高于i的比特,全部和ans的高位保持一致;同时x的第i位一定是0(低位无限制)。
  2. 2. 单行判断分支:
    • • 若该行找到任意一个x满足条件:说明本行可以选出一个「高位匹配ans、第i位为0」的数字,本行校验通过,直接跳过本行剩余数字,进入下一行校验;
    • • 若本行全部数字都不满足条件:本行不存在能让第i位为0的数字,说明最终答案的第i位必须置1

2.3 根据校验结果更新ans

  1. 1. 若所有行都能找到符合条件的数字:当前第i位可以保持0,ans不做任何修改,直接处理下一个更低的比特位;
  2. 2. 若存在任意一行找不到符合条件的数字:第i位无法为0,执行 ans |= 1 << i,把ans的第i位强制设为1,再处理下一个低位比特。

示例逐位推演 grid=[[1,5],[2,4]]

初始:ans=0,or=3,二进制长度2,i从1开始(高位),再i=0。

第1位(i=1,2^1=2)

mask = ans | (1<<1 -1) = 0 | 1 = 0b01 逐行校验:

  • • 第一行数字1(0b01)、5(0b101) x=1:1 | 0b01 = 0b01 = mask,满足,本行通过;
  • • 第二行数字2(0b10)、4(0b100) x=2:2 | 0b01 = 0b11 ≠ mask;x=4同理不满足。本行无符合条件数字。 结论:第1位必须为1,ans = 0 | (1<<1) = 2(0b10)。
第0位(i=0,2^0=1)

mask = ans | (1<<0 -1) = 2 | 0 = 0b10 逐行校验:

  • • 第一行数字1(0b01):1 | 0b10 = 0b11≠0b10;5(0b101):5 | 0b10=0b111≠0b10,无匹配?修正校验逻辑: 判断目标:数字高位和ans(0b10)一致,第0位为0。 数字高位是高于0的位(即第1位),必须等于ans第1位=1,同时第0位=0。 第一行:1二进制01(第1位是0,不匹配ans高位)、5是101(第1位0,不匹配); 第二行:2是10(第1位1,第0位0,满足x|mask=10=mask)。 此时第一行没有满足条件的数字,说明第0位必须置1,ans = 2 | 1 = 3,循环结束。

最终ans=3,和题目输出一致。

步骤3:遍历完成所有比特位,返回ans

从高到低所有比特全部判断完毕,ans就是每行选一个数得到的最小或结果。

二、时间复杂度分析

变量定义

设总元素数量 T = m * n,题目约束 T ≤ 1e5; 设数字最大二进制位数 B:grid[i][j] ≤ 1e5,1e5二进制约17位,B≈17(常数)。

  1. 1. 第一步求每行最小值并计算初始or:遍历全部T个元素,复杂度 O(T);
  2. 2. 外层比特循环:B次循环,B是固定常数;
  3. 3. 每层比特循环内部:遍历全部T个数字做校验,单次内层O(T); 总时间复杂度: O(T + B * T) = O(B*T) B为常数,等价于 O(T),即 O(m*n)。

三、额外空间复杂度分析

代码仅使用固定数量临时变量:or、ans、i、mask、循环临时行row、数字x,无额外数组、切片、哈希表等动态存储; 不随输入规模m、n、T增长开辟存储空间。 额外空间复杂度:O(1)(常数空间)。

Go完整代码如下:

.

代码语言:javascript
复制
package main

import (
    "fmt"
    "math/bits"
    "slices"
)

func minimumOR(grid [][]int) (ans int) {
    or := 0
    for _, row := range grid {
        // 每行选个最小值,计算 OR
        or |= slices.Min(row)
    }
    // 答案 <= or,那么答案的二进制长度也 <= or 的二进制长度

    // 试填法:ans 的第 i 位能不能是 0?
    // 如果在每一行的能选的数字中,都存在第 i 位是 0 的数,那么 ans 的第 i 位可以是 0,否则必须是 1
    for i := bits.Len(uint(or)) - 1; i >= 0; i-- {
        mask := ans | (1<<i - 1) // mask 低于 i 的比特位全是 1,表示 grid[i][j] 的低位是 0 还是 1 无所谓
    next:
        for _, row := range grid {
            for _, x := range row {
                // x 的高于 i 的比特位,如果 mask 是 0,那么 x 的这一位必须也是 0(注意 mask 继承了 ans 高位中的 0)
                // x 的低于 i 的比特位,随意
                // x 的第 i 个比特位,我们期望它是 0
                if x|mask == mask { // x 可以选,且第 i 位是 0
                    continue next
                }
            }
            // 这一行的可选数字中,第 i 位全是 1
            ans |= 1 << i // ans 第 i 位必须是 1
            break         // 填下一位
        }
    }
    return
}

func main() {
    grid := [][]int{{1, 5}, {2, 4}}
    result := minimumOR(grid)
    fmt.Println(result)
}
在这里插入图片描述
在这里插入图片描述

Python完整代码如下:

.

代码语言:javascript
复制
# -*-coding:utf-8-*-

from typing import List

def minimumOR(grid: List[List[int]]) -> int:
    # 计算每行最小值的 OR,作为答案的上界
    or_val = 0
    for row in grid:
        or_val |= min(row)

    ans = 0
    # 从最高位向最低位尝试填 0
    for i in range(or_val.bit_length() - 1, -1, -1):
        # mask: 高于 i 的位与 ans 一致,低于 i 的位全为 1(可任意),第 i 位为 0
        mask = ans | ((1 << i) - 1)
        for row in grid:
            for x in row:
                # 如果 x 满足:高位与 ans 已固定的 0 对齐,且第 i 位为 0
                if (x | mask) == mask:
                    break
            else:
                # 这一行找不到满足条件的数,第 i 位必须填 1
                ans |= (1 << i)
                break
    return ans


if __name__ == "__main__":
    grid = [[1, 5], [2, 4]]
    result = minimumOR(grid)
    print(result)
在这里插入图片描述
在这里插入图片描述

C++完整代码如下:

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <algorithm>

int minimumOR(const std::vector<std::vector<int>>& grid) {
    // 计算每行最小值的按位或,作为答案的上界
    int orVal = 0;
    for (const auto& row : grid) {
        orVal |= *std::min_element(row.begin(), row.end());
    }

    // 计算 orVal 的二进制长度(位数)
    int bits = 0;
    int tmp = orVal;
    while (tmp) {
        ++bits;
        tmp >>= 1;
    }

    int ans = 0;
    // 试填法:从高位到低位尝试让 ans 的第 i 位为 0
    for (int i = bits - 1; i >= 0; --i) {
        // mask: 低于 i 的位全为 1,第 i 位为 0,高于 i 的位与 ans 保持一致
        int mask = ans | ((1 << i) - 1);

        bool possible = true;
        for (const auto& row : grid) {
            bool rowOk = false;
            for (int x : row) {
                // 检查 x 是否满足:高位对齐 ans 的 0 位,且第 i 位为 0
                if ((x | mask) == mask) {
                    rowOk = true;
                    break;
                }
            }
            if (!rowOk) {
                possible = false;
                break;
            }
        }

        // 如果某一行无法选出第 i 位为 0 的数,则 ans 的第 i 位必须为 1
        if (!possible) {
            ans |= (1 << i);
        }
    }

    return ans;
}

int main() {
    std::vector<std::vector<int>> grid = {{1, 5}, {2, 4}};
    int result = minimumOR(grid);
    std::cout << result << std::endl;
    return0;
}
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、代码整体执行分步详细流程
    • 步骤1:先计算所有行最小值的或值 or,确定二进制遍历上限
    • 步骤2:从最高二进制位往低位逐位贪心判断,构造最小答案ans
      • 2.1 构造校验掩码 mask
      • 2.2 逐行校验:是否每行都存在符合条件的数字
      • 2.3 根据校验结果更新ans
      • 示例逐位推演 grid=[[1,5],[2,4]]
    • 步骤3:遍历完成所有比特位,返回ans
  • 二、时间复杂度分析
    • 变量定义
  • 三、额外空间复杂度分析
  • Go完整代码如下:
  • Python完整代码如下:
  • C++完整代码如下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档