当前位置: 首页 > news >正文

千问 LeetCode 2732. 找到矩阵中的好子集 Java实现

这是一道结合了位运算与数学规律(贪心)的巧妙题目。

💡 核心思路

题目要求找到一个非空的行子集,使得子集中每一列的元素和不超过子集大小的一半(即 le lfloor k/2 rfloor,其中 k 是选出的行数)。

直接暴力枚举所有子集(2^m 种情况)会超时。但这道题有一个非常关键的数学性质:如果存在一个大小 k ge 3 的好子集,那么一定存在一个大小为 1 或 2 的好子集。

因此,我们只需要寻找以下两种情况即可:
1. 大小为 1 的好子集:即矩阵中是否存在某一行,它的所有元素都是 0。此时列和为 0,满足 le lfloor 1/2 rfloor = 0。
2. 大小为 2 的好子集:即是否存在两行,它们在任意同一列上不同时为 1。如果两行在某列上同时为 1,该列和为 2,不满足 le lfloor 2/2 rfloor = 1。

🔍 为什么只需要考虑 1 行或 2 行?

* 1 行的情况:显然,只有全 0 的行才满足条件。
* 2 行的情况:只要两行在每一列上的和 le 1 即可。这意味着两行在二进制表示下,按位与(&)的结果必须为 0。
* 3 行及以上的情况:题目中矩阵的列数 n 最多只有 5。根据抽屉原理和反证法可以证明,如果存在一个更大的好子集,我们总能从中抽离出满足条件的 1 行或 2 行。因此,只要找不到 1 行或 2 行的解,更大的解也一定不存在。

💻 Java 实现代码

我们可以利用状态压缩,将每一行压缩成一个整数(因为最多只有 5 列,用 5 位二进制即可表示)。

import java.util.*;

class Solution {
public List<Integer> goodSubsetofBinaryMatrix(int[][] grid) {
int m = grid.length;
int n = grid[0].length;

// 使用 HashMap 记录每种行状态(压缩后的整数)对应的行下标
// 如果有多行状态相同,只保留任意一个下标即可(因为只需要返回一个解)
Map<Integer, Integer> maskToIdx = new HashMap<>();

for (int i = 0; i < m; i++) {
int mask = 0;
// 状态压缩:将一行转换成一个整数
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
mask |= (1 << j);
}
}

// 情况1:找到了全为 0 的行(mask 为 0)
if (mask == 0) {
return Arrays.asList(i);
}

// 将当前行的状态存入 map(如果状态已存在,覆盖与否不影响最终寻找两行解的逻辑)
maskToIdx.put(mask, i);
}

// 情况2:寻找两行,它们的按位与结果为 0
// 这意味着这两行在任何一列上都没有同时出现 1
for (int mask1 : maskToIdx.keySet()) {
for (int mask2 : maskToIdx.keySet()) {
if ((mask1 & mask2) == 0) {
int i = maskToIdx.get(mask1);
int j = maskToIdx.get(mask2);
// 题目要求返回升序的行下标
if (i == j) continue; // 防止取到同一行(虽然全0行在上面已经返回了,这里防御一下)
return i < j ? Arrays.asList(i, j) : Arrays.asList(j, i);
}
}
}

// 如果找不到大小为 1 或 2 的好子集,根据数学规律,更大的子集也不存在
return new ArrayList<>();
}
}

📊 复杂度分析

* 时间复杂度:O(m cdot n + U^2)。
* 遍历矩阵进行状态压缩需要 O(m cdot n)。
* 由于列数 n le 5,不同的行状态最多只有 2^5 = 32 种(即 U = 32)。双重循环遍历这些状态的时间是 O(32^2),这是一个极小的常数。
* 整体效率非常高。
* 空间复杂度:O(U),即 O(32),用于存储不同行状态的下标映射。

http://www.rkmt.cn/news/1400803.html

相关文章:

  • 梅州市黄金回收 白银回收 铂金回收 彩金回收全攻略:五家靠谱门店横向评测,附避坑要点 - 前途无量YY
  • 多智能体系统身份安全:从共享凭证到独立密码学身份的实践指南
  • 性价比高的卫浴定制公司怎么选?哈尔滨悦滢国际卫浴来帮你 - mypinpai
  • 如何快速搭建智能媒体中心:MetaTube插件终极配置指南
  • 3个步骤让PS手柄秒变PC游戏神器:DS4Windows完全指南
  • 蒙自市黄金回收 白银回收 铂金回收 彩金回收全攻略:五家靠谱门店横向评测,附避坑要点 - 前途无量YY
  • 智能驾驶的“超级导航员”:一文读懂高精度地图的前世今生与未来
  • 弥勒市黄金回收 白银回收 铂金回收 彩金回收全攻略:五家靠谱门店横向评测,附避坑要点 - 前途无量YY
  • 汽车大屏导航安装,如何选择靠谱店铺? - mypinpai
  • listmonk数据库连接超时处理:提升系统稳定性
  • listmonk数据库查询重写:提升性能的高级技巧
  • 临一云川浮空风电非线性稳定的五行求解模型
  • 别再死记硬背了!用Arduino和面包板,5分钟搞懂三极管开关电路(附代码)
  • 物理信息神经网络梯度优化与二阶方法实践
  • 绵阳市黄金回收 白银回收 铂金回收 彩金回收全攻略:五家靠谱门店横向评测,附避坑要点 - 前途无量YY
  • Go语言零内存分配PII擦除:从正则表达式到高性能状态机实战
  • listmonk与客户反馈闭环:从收集到改进的流程
  • Granite Guardian 3.0-2B完全指南:从开源贡献到问题解决的终极教程 [特殊字符]
  • Vivado工程文件太大?三步教你用reset_project和Tcl脚本给源码“瘦身”,轻松备份到Git
  • 绵竹市黄金回收 白银回收 铂金回收 彩金回收全攻略:五家靠谱门店横向评测,附避坑要点 - 前途无量YY
  • 终极Office文件预览指南:Windows空格键快速查看文档
  • 别急着删资料!华硕ASUS电脑重装Win7前,用DiskGenius这样备份和转换分区最安全
  • 明光市黄金回收 白银回收 铂金回收 彩金回收全攻略:五家靠谱门店横向评测,附避坑要点 - 前途无量YY
  • 告别台式机?实测用笔记本+FPGA开发板搭建轻量级PCIE验证环境(避坑指南)
  • 湖北建筑工程资质代办选哪家?资深从业者拆解靠谱选项 - 奔跑123
  • G4-MeroMero-31B vs 原版Gemma4:创意任务性能对比分析
  • Cat-Catch智能资源嗅探实战:构建高效网页媒体下载工作流
  • OpenClaw数据采集实战:从技术原理到商业变现的完整指南
  • 3分钟让Figma说中文!设计师必备的界面汉化神器
  • Unity 2022.3 + ShaderGraph 实战:5分钟搞定刮刮乐游戏,从RenderTexture到UI交互全流程