【问题标题】:Fastest Way To Reverse Long Java [duplicate]反转长 Java 的最快方法 [重复]
【发布时间】:2020-11-24 00:37:03
【问题描述】:

反转Long 值的最快方法是什么?

例如,9876543210 应该返回 0123456789

这就是我现在拥有的:

long n = 0, c = 987654321 * 10; // *10 is to get 9876543210 as long value;
while (c > 0) n = n * 10 + c % 10;
System.out.println(n);

【问题讨论】:

  • "*10 是获取 9876543210 作为 long 值;" - 你可以这样做 9876543210L
  • 将long值转换为字符串,然后反转字符串。见Reverse a string in Java
  • 如果你保持很长,那个前导零每次都会被剥离。

标签: java reverse long-integer


【解决方案1】:

我认为这可以很快

long x = 1234567890L;
String reversed = new StringBuilder(Long.toString(x)).reverse().toString();

// reversed = "0987654321"

如果您想再次将反转的值转换为long

long x = -1234567890000L;
StringBuilder reversed = new StringBuilder(Long.toString(x)).reverse();

System.out.println(reversed); // 0000987654321-

if (reversed.charAt(reversed.length() - 1) == '-') //remove `-` at last position
{
    reversed.setLength(reversed.length() - 1);
}

while (reversed.charAt(0) == '0') //remove all `0` at the beginning 
{
    reversed.replace(0, 1, "");
}

System.out.println(reversed); // 987654321

long newLong = Long.parseLong(reversed.toString());

【讨论】:

  • @georgezhang006 请注意,从String 回到long,例如by Long.parseLong(reversed) 可能会去掉前导零,从而导致 987654321
  • 是的,当然。我不知道提问者想如何使用这个反向值,但如果作为一个数字,在开头修剪 0 并在结尾修剪 - 很重要
【解决方案2】:

您可以简单地转换为字符串,然后恢复字符串,特别是如果您希望最终输出字符串。这应该是非常直接的,并且它具有前导 0,它也可能比为每个位置进行计算更快(但 valueOf 的转换成本可能会抵消该优势):

    long c = 9876543210L;
    String cAsString = String.valueOf(c);
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < cAsString.length(); i++) {
        builder.append(cAsString.substring(cAsString.length() - (i + 1), cAsString.length() - i));
    }
    System.out.println(builder.toString());

或作为一个班轮

    long c = 9876543210L;
    String reverted = new StringBuilder(String.valueOf(c)).reverse().toString();
    System.out.println(reverted);

我对当前答案的选项做了一点比较:

    public static void main(String[] args) {
    Instant start = Instant.now();
    for (long i = 0; i < 100_000_000; i++) {
        stringbuilderWithDirectCalcs(i);
    }
    Duration duration = Duration.between(start, Instant.now());
    System.out.println("Took " + duration);
}


protected static void stringbuilderWithDirectCalcs(long value) {
    final StringBuilder sb = new StringBuilder();
    while (value > 0) {
        sb.append(value % 10);
        value /= 10;
    }
    // System.out.println(sb.toString());
}


protected static void stringbuilderConvenient(long value) {
    String reverted = new StringBuilder(String.valueOf(value)).reverse().toString();
    //System.out.println(reverted);
}


protected static void stringbuilderHandCrafted(long value) {
    String cAsString = String.valueOf(value);
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < cAsString.length(); i++) {
        builder.append(cAsString.substring(cAsString.length() - (i + 1), cAsString.length() - i));
    }
    //System.out.println(builder.toString());
}

我每次跑了三个。结果:

stringbuilderConvenient
Took PT6.988S /  Took PT6.8S / Took PT6.68S


stringbuilderWithDirectCalcs:
Took PT6.17S / Took PT6.776S / Took PT6.692S


stringbuilderHandCrafted
Took PT18.205S / Took PT16.035S / Took PT17.025S

因此,手动扫描 String 并逐步将 StringBuilder 粘在一起似乎是不可能的。显然,斯蒂芬 C 在他的评论中是正确的,即在转换为字符串时无论如何都会发生计算。但是基于 Stringbuilder.reverse 和手动计算每个位置的方法非常接近(任何差异都可能是由于运行时的微小波动)。因此,人们可能会选择 StringBuilder.reverse 方法而不是手动计算每个位置,以获得大致相同的性能的可读性。

【讨论】:

  • 除了不避免对每个位置进行计算。它们发生在valueOf 内部。看源码...
【解决方案3】:

您的程序遇到无限循环,因为您从未更改 c 的值。在每次迭代结束时添加c /= 10,它会起作用,尽管前导零会因为它是一个数字而被删除。

long n = 0, c = 9876543210L; 
while (c > 0){
    n = n * 10 + c % 10;
    c /= 10;
}
System.out.println(n);

如果您需要前导零,则应考虑使用Strings。

long c = 9876543210L;
final StringBuilder sb = new StringBuilder();
while (c > 0){
    sb.append(c % 10);
    c /= 10;
}
System.out.println(sb.toString());

【讨论】:

  • 使用 String.fromValue() 然后恢复它不会更快吗?没有计算只涉及“数组”操作......
  • @FrankHopkins 你有什么建议?
  • @FrankHopkins - 我不确定一定会这样。 Long -> String 转换在引擎盖下重复除以 10 和模数 10。你为什么不尝试一个实验?
  • 该死,对不起...我编辑了您的答案而不是我的...将寻找撤消按钮...
  • @FrankHopkins 别担心。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
  • 2021-08-29
  • 2012-08-10
  • 2017-10-18
  • 1970-01-01
  • 2017-12-09
  • 1970-01-01
相关资源
最近更新 更多