按位与为0的三元组【详解】
创始人
2024-05-28 21:17:21
0

这个题目我也是绕了很久才想明白其核心的思想,以下给出我对于该题目解法的理解。
关键字:位运算、枚举+子集优化

题目:按位与为0的三元组
给你一个整数数组 nums ,返回其中 按位与三元组 的数目。
按位与三元组 是由下标 (i, j, k) 组成的三元组,并满足下述全部条件:

0 <= i < nums.length
0 <= j < nums.length
0 <= k < nums.length
nums[i] & nums[j] & nums[k] == 0 ,其中 & 表示按位与运算符。

示例 1:
输入:nums = [2,1,3]
输出:12
解释:可以选出如下 i, j, k 三元组:
(i=0, j=0, k=1) : 2 & 2 & 1
(i=0, j=1, k=0) : 2 & 1 & 2
(i=0, j=1, k=1) : 2 & 1 & 1
(i=0, j=1, k=2) : 2 & 1 & 3
(i=0, j=2, k=1) : 2 & 3 & 1
(i=1, j=0, k=0) : 1 & 2 & 2
(i=1, j=0, k=1) : 1 & 2 & 1
(i=1, j=0, k=2) : 1 & 2 & 3
(i=1, j=1, k=0) : 1 & 1 & 2
(i=1, j=2, k=0) : 1 & 3 & 2
(i=2, j=0, k=1) : 3 & 2 & 1
(i=2, j=1, k=0) : 3 & 1 & 2

示例 2:
输入:nums = [0,0,0]
输出:27

思维流程:

观察示例一,我们可以很自然的想到三重循环的暴力解法,但是这种方式显然是不行的。参考了官方的解法和排行第二的解法,以下给出一种更为直观和通俗的理解方法。
(1) 二进制子集的概念
把二进制数看成集合,二进制从低到高第 i 位为 1 表示 i 在集合中,为 0 表示 i 不在集合中,例如 a = 1101 --> { 0, 2, 3 }。
(2)补集的概念
A & B = 0,相当于用二进制子集表示的A集合与B集合没有交集,也可以理解为B是A的补集的子集,或者A是B补集的子集。本题中 U = { 0,1,2,…,15 } ,全集对应的数字就是 0xffff 。一个数字异或 0xffff 就可以得到它的补集。

懂了这两个概念再顺一遍整体的思维过程:
先写一个O(n^2)的枚举,计算所有的nums[ i ] & nums[ j ] 。它们相与的结果,也就是两个集合的交,一定是在全集U中的,所以需要一个 2^16 大小的数组,用来保存每种相与集合出现的次数。
然后再枚举全集中每种集合的补集,如果在之前的计算结果中出现了当前位置的补集,那么反向思考之前计算过的集合和当前枚举的集合互为补集,就构成了一个三元组,这三个集合相与就是0。

注意: 考虑空集 当 s = 0 时,再减一,又会回到全1的情况,补码的性质。

示例代码:

class Solution {
public:int countTriplets(vector &nums) {int cnt[1 << 16]{};//先枚举两个集合相与的结果for (int x : nums)for (int y : nums)//相与后的结果对应数组的下标,数组中保存该集合出现的次数++cnt[x & y];int ans = 0;for (int m : nums) {//m表示全集m ^= 0xffff;//利用s变量,枚举所有可能的子集,s从全集开始取int s = m;do { // 枚举 m 的子集(包括空集)ans += cnt[s];//(s-1)&m 表示数组中从右往左,下一个集合的补集//如果该补集在第一个循环中计算中出现过,那么就形成了按位与为0的三元组s = (s - 1) & m;} while (s != m);}return ans;}
};

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...