每日算法 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]外加一个括号。还有就是一开始被这层二进制的皮和标题以及难度为困难吓住了,想的有点复杂,没想到拨开外衣其实也是可以暴力破解的(虽然超时了),还是有待提高。
标签:nums,int,每日,三元组,运算符,++,算法,按位,230304 From: https://www.cnblogs.com/tyrantblue/p/17179289.html