【问题标题】:Convert int to Hex String without using Integer.toHexString();不使用 Integer.toHexString() 将 int 转换为十六进制字符串;
【发布时间】:2017-03-12 09:20:07
【问题描述】:

以下是问题陈述 LeetCode.

给定一个整数,编写一个算法将其转换为十六进制。为了 负整数,采用补码法。

注意:

  • 十六进制 (a-f) 中的所有字母必须小写。

  • 十六进制字符串不能包含额外的前导 0。如果数字为零,则由单个零字符“0”表示; 否则,十六进制字符串中的第一个字符将不会 零字符。

  • 给定的数字保证在 32 位有符号整数的范围内。

  • 您不得使用库提供的任何直接将数字转换/格式化为十六进制的方法

这是我的解决方案:

public class Solution {
    private static final String characters = "0123456789abcdef";
    private static final char[] digits = characters.toCharArray(); 
    
    private Stack<Integer> stack = new Stack<>();
    public String toHex(int num) {
        if (num == 0) return "0";
        
        stack.clear();
        while (num != 0) {
            stack.push(getDigit(num));
            num = num >>> 4;
            System.out.println(num);
            if (stack.size() > 8) break;
        }
        
        StringBuilder buffer = new StringBuilder();
        while (!stack.empty()) {
            buffer.append(digits[stack.pop()]);
        }
        
        return buffer.toString();
    }
    
    private int getDigit(int num) {
        int result = num & 0xF;
        return result;
    }
}

问题是这个解决方案有效,但它的性能不是很好——我在这个解决方案的运行时中处于最低 1% 的位置。我想知道我对 Stack Object 或 StringBuilder 的使用是否让我很伤心。

也完全有可能大量的提交无视限制并使用 Java API。 :) 但我想我会在这里发帖并了解如何提高效率。

【问题讨论】:

  • 你可以用大尺寸初始化 StringBuilder。当 char [ ] (StringBuilder 中的数组)已满时,它将为您节省大量冗余复制
  • 一些 java 专家可以看看这段代码,并告诉你什么比它应该花费的时间更长。我们其他人需要使用分析器。我不确定 Stack 实现会带来多少开销(如果有的话)。此外,时间上的差异和 Java 的性质可能意味着下次运行代码时只需 10 毫秒。
  • 可能更适合Code Review
  • 尝试删除您当前在循环中的System.out.println()。这可能会显着增加执行时间。
  • @Marvin 谢谢,没有意识到该站点可用。下次我试试看。

标签: java algorithm binary hex


【解决方案1】:

我只对您的代码进行了一些调整,就实现了一个小的改进。

我将运行时间缩短了 8 毫秒,使其超过了 51.90% 的其他解决方案。

public class Solution {
    private static final char[] digits = "0123456789abcdef".toCharArray(); 

    private Stack<Integer> stack = new Stack<>();
    public String toHex(int num) {
        if (num == 0) return "0";

        stack.clear();
        while (num != 0) {
            stack.push(num & 0xF);
            num = num >>> 4;
            if (stack.size() > 8) break;
        }

        StringBuilder buffer = new StringBuilder();
        while (!stack.empty()) {
            buffer.append(digits[stack.pop()]);
        }

        return buffer.toString();
    }
}

首先,我改变了digits数组的构造方式,将原来的两行压缩成一行。

我还删除了System.out.println 电话。

最后,我将getDigit() 方法的调用替换为内嵌在主代码中的内容。

* 更新 *

这也是一个更简洁的选项,将循环数减少到一个并且无需使用Stack

public class Solution {
    private static final char[] digits = "0123456789abcdef".toCharArray(); 

    public String toHex(int num) {
        if (num == 0) return "0";

        StringBuilder buffer = new StringBuilder();
        while (num != 0) {
            buffer.append(digits[num & 0xF]);
            num = num >>> 4;
        }
        return buffer.reverse().toString();
    }
}

注意:这个性能似乎在 7ms 和 8ms 之间波动。

【讨论】:

  • 我完全忽略了 println 调用...谢谢!很好的反向调用——很高兴知道 stringbuilder 具有这种能力。
【解决方案2】:

通过进行这些更改来减少工作量:

  • 丢失堆栈。这很方便,但考虑到这是“数学”任务,相对较重
  • 不要使用char[],使用byte[] 作为输出字符'0''f'。所有字符都 byte 就足够了。这也意味着您可以使用已弃用但快速且理想的构造函数public String(byte[] ascii, int hibyte, int offset, int count)
  • 将结果保存在byte[8]
  • 捕获所有 8 个 4 位半字节。如果 nybble[i] 不为零,则将输出字节放在索引 i 处结果中 nybble 的索引处。如果它是 first 非零值,请记住 i 并将其用作 offset
  • 使用0hibyte8 - start 调用前面提到的构造函数为count

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-04
    • 2020-07-18
    • 1970-01-01
    • 2021-01-26
    相关资源
    最近更新 更多