正如评论中提到的,要获得更有效的解决方案,请使用<< 位移运算符和Integer.numberOfLeadingZeros(i) 方法:
static long binaryConcatRange(int n) {
if (n < 0 || n > 17)
throw new IllegalArgumentException("Out of range (0-17): " + n);
long result = 0;
for (int i = 1; i <= n; i++) {
int bitLen = 32 - Integer.numberOfLeadingZeros(i);
result = (result << bitLen) | i;
}
return result;
}
对于一个可能1更有效的解决方案,它可以在没有numberOfLeadingZeros() 方法的情况下完成:
static long binaryConcatRange(int n) {
if (n < 0 || n > 17)
throw new IllegalArgumentException("Out of range (0-17): " + n);
long result = 0;
for (int bitLen = 0, nextLenAt = 1, i = 1; i <= n; i++) {
if (i == nextLenAt) {
bitLen++;
nextLenAt <<= 1;
}
result = (result << bitLen) | i;
}
return result;
}
1) 方法 numberOfLeadingZeros() 使用 @HotSpotIntrinsicCandidate 注释,因此使用本机解决方案可能会超快,这意味着此 Java 代码替代方案可能不会更快。
测试
for (int n = 0; n < 18; n++)
System.out.printf("%s: %s%n", n, binaryConcatRange(n));
输出
0: 0
1: 1
2: 6
3: 27
4: 220
5: 1765
6: 14126
7: 113015
8: 1808248
9: 28931977
10: 462911642
11: 7406586283
12: 118505380540
13: 1896086088653
14: 30337377418462
15: 485398038695407
16: 15532737238253040
17: 497047591624097297
要支持大于 17 的 n 值,必须将返回类型更改为 BigInteger:
static BigInteger binaryConcatRange(int n) {
if (n < 0 || n == Integer.MAX_VALUE)
throw new IllegalArgumentException("Out of range: " + n);
BigInteger result = BigInteger.ZERO;
for (int i = 1; i <= n; i++) {
int bitLen = 32 - Integer.numberOfLeadingZeros(i);
result = result.shiftLeft(bitLen).or(BigInteger.valueOf(i));
}
return result;
}
测试
for (int n = 18; n < 32; n++)
System.out.printf("%s: %s%n", n, binaryConcatRange(n));
for (int n = 32; n <= 256; n *= 2)
System.out.printf("%s: %s%n", n, binaryConcatRange(n));
输出
18: 15905522931971113522
19: 508976733823075632723
20: 16287255482338420247156
21: 521192175434829447909013
22: 16678149613914542333088438
23: 533700787645265354658830039
24: 17078425204648491349082561272
25: 546509606548751723170641960729
26: 17488307409560055141460542743354
27: 559625837105921764526737367787355
28: 17908026787389496464855595769195388
29: 573056857196463886875379064614252445
30: 18337819430286844380012130067656078270
31: 586810221769179020160388162164994504671
32: 37555854193227457290264842378559648298976
64: 471483835060474447584605138071473227083738554722043752192205889593231757234798071314332600270577600
128: 685385418402711161486992779215452480197156956593160845028648293349782283935659509581295718147533155031188929619519081596427609304635849304708531968190976802229890594798789934166770532152593884743090295308624351511929798643557538430848
256: 246422532279457970240939131862416256957912100676567284022182930350788567839691502682935548861928505318417306075544389639956672552326580169008528080129830322429712508593083839769096175727133924908330823876506697567963272081220317027757129623022363719594776044926884107531078136465754901556922215598679264299348040837049670711753684521748473384638643859758271742330378295219493243936419532611365679896772551640598210176805609455785828091793688653809020045393677303410807761070390084298154799431073337833749694111293934995919750974732669988765440