我正在尝试使用最有效的算法来反转Java中的大整数。 例如。如果我们必须撤销301324354432。
直到现在我有以下代码:
public int reverse(int x) {
int result = 0;
while (x != 0)
{
int tail = x % 10;
int newResult = result * 10 + tail;
if ((newResult - tail) / 10 != result)
{ return 0; }
result = newResult;
x = x / 10;
}
return result;
}
在最佳时间复杂度下实现此目标的正确算法是什么?
答案 0 :(得分:3)
一种有效的方法是如下所示(类似于你的建议)。
public static long reverse(long x) {
long y = 0;
while(x > 0) {
y = y * 10 + x % 10;
x = x / 10;
}
return y;
}
这避免了昂贵的字符串转换,只有一个通过数字并且不使用任何内存(除了存储结果)。
修改强>
一种更有效的方法,避免除法和模运算:
public static long reverse(int _x) {
long x = _x;
long y = 0;
while (x > 0) {
y = x + (y - ((x * 0x1999999Al) >> 32)) * 10; //y * 10 + x - (x/10) * 10;
x = ((x * 0x1999999Al) >> 32);
}
return y;
}
我还尝试使用bitshift操作(x * 10 = (x << 3) + (x << 1)
)将乘法乘以10,但它似乎并没有影响性能。
最高回答of this stackoverflow question显示了如何快速划分10个。为了完整性,提供的答案表明可以按照以下方式完成(归功于John Källén)
int32_t div10(int32_t dividend) {
int64_t invDivisor = 0x1999999A;
return (int32_t) ((invDivisor * dividend) >> 32);
}
此方法仅允许反转整数(最多2^31 - 1
)。结果很长,2^31 - 1 = 2147483647
和reverse(2147483647) = 7463847412 > 2^31 - 1
。
在x
上执行模10操作的快速方法是将其除以并乘以10,然后从x
中减去该结果。
答案 1 :(得分:1)
public int reverse(int x) {
int result = 0;
StringBuffer sb = new StringBuffer(0);
sb.append(x);
result = Integer.parseInt(sb.reverse().toString());
return result;
}
答案 2 :(得分:0)
您可以利用Java lambda表达式。您所要做的就是将数字转换为String,使用lambda将其反转,然后转换回int。此代码的一点变化可以允许反转任意数量的字符。这里:
public static int reversal(int x) {
String tmp = String.valueOf( x );
String result = Pattern.compile(" +").splitAsStream( tmp ).map(word->new StringBuilder(word).reverse())
.collect(Collectors.joining(" "));
return Integer.parseInt( result );
}