将int转换为Hex String而不使用Integer.toHexString();

时间:2016-10-29 19:17:58

标签: java algorithm binary hex

在你downvote之前:这是一个LeetCode问题。阅读下面的规则,你就会明白为什么我没有使用任何为我这样做的Java API。

以下是问题陈述 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是否会让我感到悲伤。

enter image description here

大量的提交也完全有可能忽略了限制并且无论如何都使用Java API。 :)但我想我会在这里发布并学习如何让这个更有效率。

2 个答案:

答案 0 :(得分:3)

我只需对您的代码进行一些调整即可实现一项小改进。

enter image description here

我在运行时间缩短了8ms,将其移动到其他解决方案的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();
    }
}

enter image description here

注意:这种情况的表现似乎在7毫秒到8毫秒之间波动。

答案 1 :(得分:2)

通过进行这些更改做得更少:

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