我正在写一个leetCode问题,要求我输出一个整数的补码整数。 LeetCode#476
我一直认为位操作很快,因为在最后,一切都是通过位操作来完成的。但是在这个问题中,字符串方法比位操作更快,我想知道为什么。
我写了一个11ms接受的字符串操作代码。代码如下,非常直观。
class Solution {
public int findComplement(int num) {
String s = Integer.toBinaryString(num);
StringBuilder sb = new StringBuilder();
for(char c : s.toCharArray()){
sb.append(c == '1' ? 0 : 1);
}
int ret = Integer.parseInt(sb.toString(), 2);
return ret;
}
}
我偷看了讨论,发现了一些解决问题的操作,我试了一下。然而,它被接受了13ms。以下是代码。
class Solution {
public int findComplement(int num) {
return ~num & ((Integer.highestOneBit(num) << 1) - 1);
}
}
答案 0 :(得分:1)
我确定LeetCode的时间安排有点可疑。
首先,我提交了几次位操作解决方案,时间从11到14毫秒不等。
然后,我提交了以下代码的各种版本,迭代次数不同:
public int findComplement(int num) {
int ret = 0;
for (int i = 1; i <= 2000000; i++)
ret |= ~num & ((Integer.highestOneBit(num) << 1) - 1);
return ret;
}
结果:
Number of iterations Time/ms
-------------------- -------
1 11
10 17
20 14
200 32
20000 39
2000000 145
特别注意,20次迭代只需不到10次迭代。但总体而言,时间与迭代相比呈上升趋势。我认为LeetCode没有足够的时间调用该方法来做任何有意义的时间。
这是一种更快的方法:
public int findComplement(int num) {
int usedBits = num;
usedBits |= usedBits >> 1;
usedBits |= usedBits >> 2;
usedBits |= usedBits >> 4;
usedBits |= usedBits >> 8;
usedBits |= usedBits >> 16;
return ~num & usedBits;
}
对于2000000次迭代,上述情况需要130 ms,与之前的145 ms相比有利。
现在让我们尝试使用您的StringBuilder方法进行迭代:
public int findComplement(int num) {
int ret = 0;
for (int i = 1; i <= 20000; i++) {
String s = Integer.toBinaryString(num);
StringBuilder sb = new StringBuilder();
for(char c : s.toCharArray()){
sb.append(c == '1' ? 0 : 1);
}
ret |= Integer.parseInt(sb.toString(), 2);
}
return ret;
}
时间:785 ms(比特操作解决方案为37 ms)