每日算法 230304
题目
给你一个整数数组 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 <= nums.length <= 1000
0 <= nums[i] < 2^16
来源:力扣(LeetCode)
思路
因为nums[i]在1到2^16之间,按照2进制来说最大为16位。题目要求是nums[i] & nums[j] & nums[k] == 0,只要三个数的所有相同位上都至少有1个0,那么要求就成立。那么就是如何判断每个相同位都有1个0了,嗯,,,没有思路,只能暴力破解了
解题
class Solution { public int countTriplets(int[] nums) { int sum = 0; //暴力循环判断 for (int i = 0; i < nums.length; i++) { for (int j = 0; j < nums.length; j++) { for (int k = 0; k < nums.length; k++) { if ((nums[i]&nums[j]&nums[k]) == 0){ sum++; } } } } return sum; } }
果不其然超出了时间限制
要是能优化一下能跳过重复的查询就好
官方解答如下:
class Solution { public int countTriplets(int[] nums) { int[] cnt = new int[1 << 16]; for (int x : nums) { for (int y : nums) { ++cnt[x & y]; } } int ans = 0; for (int x : nums) { for (int mask = 0; mask < (1 << 16); ++mask) { if ((x & mask) == 0) { ans += cnt[mask]; } } } return ans; } }
总结
在写的时候遇到了判断时逻辑运算符和关系运算符的优先级问题,优先级为关系运算符大于逻辑运算符,所以要在nums[i]&nums[j]&nums[k]外加一个括号。还有就是一开始被这层二进制的皮和标题以及难度为困难吓住了,想的有点复杂,没想到拨开外衣其实也是可以暴力破解的(虽然超时了),还是有待提高。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步