我正在尝试使用Java 8的新功能(例如Stream
s)在Hacker Rank site的位操作部分解决以下问题。
问题描述:
给定一个整数n,找到每个x,使得:
- 0< = x< = n
- n + x = n ^ x
其中^表示按位XOR运算符。然后打印一个整数,表示满足上述条件的x的总数。
约束
- 0< = n< = 10 15
示例输入: 5
示例输出: 2
解释
对于 n = 5 , x 值 0 和 2 满足条件:
- 5 + 0 = 5 ^ 0 = 5
- 5 + 2 = 5 ^ 2 = 7
因此,我们打印 2 作为我们的答案。
示例输入: 10
示例输出: 4
说明: 对于 n = 10 , x 值 0 , 1 , 4 ,以及 5 满足条件:
- 10 + 0 = 10 ^ 0 = 10
- 10 + 1 = 10 ^ 1 = 11
- 10 + 4 = 10 ^ 4 = 14
- 10 + 5 = 10 ^ 5 = 15
因此,我们打印 4 作为我们的答案。
我的代码如下:
public class SumVsXor
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
long n = in.nextLong();
long count = LongStream.rangeClosed(0, n)
.filter(k -> k + n == (k ^ n))
.count();
System.out.println(count);
}
}
问题是此代码未通过所有测试用例。
它适用于n
的小值,但对于1000000000000000
这样的大值,它会因超时而失败。
我想知道LongStream
是否无法使用那么多元素来处理Stream
。
答案 0 :(得分:22)
您的代码存在问题,效率非常低。对于n==1000000000000000
的情况,您的Stream
管道正在执行1,000,000,000,000,000
添加和XOR操作,这需要很长时间。测试0到n之间的每个数字,即使使用for循环而不是n + x == n ^ x
,Stream
将花费很长时间。
您应该尝试找出一种更好的方法来计算所需的x总数,而不是检查0和n之间的所有数字。这个问题出现在“位操作”部分下的事实应该给你一个提示
查看满足n + x == n ^ x
的数字位数。
让我们考虑n==1000000000000000
的情况。该大数字的二进制表示是
0000000000000011100011010111111010100100110001101000000000000000
=== == = ====== = = = == == =
--- - - - - -- -- --- - ---------------
~~~~~~~~~~~~~~
为了使n + x
等于n ^ x
,x
必须在与0
位对应的所有位中具有1
值{1}}(上面标有n
),以及与=
的{{1}}位对应的位中的0
或1
值(标有上面0
)。这不包括前导n
s(上面标有-
),因为x必须是< = 0
,因此{{1}中的任何前导~
}} n
中的0
值也必须为n
。
这意味着0
为{2}的x的总数为x
中n + x == n ^ x
的数量,不包括前导0
}Š
对于n
,有0
个n = 1000000000000000
位,因此符合要求的30
总数为2 30
以下是计算0
总数的一种方法:
x
答案 1 :(得分:2)
我得出了相同的结果,但是通过不同的解释,我想我可以在这里发布。
Eran的回答得出了我所做的相同结论:修改初始数字的二进制表示中的零 - 这非常简单。
我们假设我们的数字是
101010100
所以它有5个零。
您需要以下所有可能的组合:
实际上是:
comb(1,5) + comb(2,5) + comb(3,5) + comb(4,5) + comb (5,5)
这是一个众所周知的公式,等于:
pow(2,n)//其中n在我们的例子中是5
从那里解决方案很明显......
答案 2 :(得分:1)
public static void main (String[] args) {
Scanner in = new Scanner (System.in);
long n = in.nextLong();
long count = 1L << (64-Long.bitCount(n)-Long.numberOfLeadingZeros(n));
System.out.println(count);
}
答案 3 :(得分:1)
如果您对XOR知之甚少,这是一个简单的问题。我不太了解java。但我可以在python中解释。
1.首先将数字转换为二进制数。 2.计算该二进制数中的零个数。 3.print 2 ^(零的数量)就是这样。
这是我的python代码。
n = int(input())
sum = 0
if n!=0:
n=str(bin(n))
for i in range(len(n)):
if n[i]=='0':
sum = sum + 1
print(2**(sum-1))
else: print(1)
将和减1的原因是,在python中它将数字转换为二进制格式。例如:0b'10101。