【问题标题】:Improve performance of string to binary number conversion提高字符串到二进制数转换的性能
【发布时间】:2019-10-03 04:59:26
【问题描述】:

这是我在竞争性编程中遇到的问题之一。

Ques) 您有一个二进制格式的输入字符串11100,您需要计算其中数字为零的步数。如果号码是odd -> subtract it by 1,如果是even -> divide it by 2

例如

28 -> 28/2

14 -> 14/2

7 -> 7-1

6 -> 6/2

3 -> 3-1

2 -> 2/2

1-> 1-1

0 -> 停止

步数 =7

我想出了以下解决方案

public int solution(String S) {
    // write your code in Java SE 8
    String parsableString = cleanString(S);
    int integer = Integer.parseInt(S, 2);
    return stepCounter(integer);
}

private static String cleanString(String S){
    int i = 0;
    while (i < S.length() && S.charAt(i) == '0')
        i++;
    StringBuffer sb = new StringBuffer(S);
    sb.replace(0,i,"");
    return sb.toString();
}

private static int stepCounter(int integer) {
    int counter = 0;
    while (integer > 0) {
        if (integer == 0)
            break;
        else {
            counter++;
            if (integer % 2 == 0)
                integer = integer / 2;
            else
                integer--;
        }
    }
    return counter;
}

这个问题的解决方案看起来非常简单明了,但是这段代码的性能评估让我得到了一个很大的零。我最初的印象是,将字符串转换为 int 是一个瓶颈,但未能找到更好的解决方案。谁能给我指出这段代码的瓶颈以及可以显着改进的地方?

【问题讨论】:

    标签: java string algorithm binary


    【解决方案1】:

    如果二进制数是奇数,则最后一位(最低有效位)必须是 1,因此减去 1 只是将最后一位从 1 更改为 0(重要的是,这会使数字变为偶数)。

    如果一个二进制数是偶数,最后一个数字必须是 0,而除以零可以通过简单地完全删除最后一个0来完成。 (就像在十进制中一样,数字 10 可以通过去掉最后的 0 来除以 1,留下 1。)

    所以步数是每1位两步,每0位一步——负1,因为当你到达最后一个0时,你不再除以2,你只是停下来.

    这是一个简单的 JavaScript(而不是 Java)解决方案:

    let n = '11100';
    n.length + n.replace(/0/g, '').length - 1;
    

    只需多做一点工作,如果需要,这也可以正确处理前导零“0011100”。

    【讨论】:

      【解决方案2】:

      您需要减去的次数是Integer.bitCount() 的位数。您需要划分的次数是最高有效位的位置,即Integer.SIZE(32,整数位数)减去Integer.numberOfLeadingZeros() 减一(您不需要划分1)。对于我假设的零输入,结果应该为零。所以我们有

      int numberOfOperations = integer == 0 ? 0 : Integer.bitCount(integer) + 
        Integer.SIZE - Integer.numberOfLeadingZeros(integer) - 1;
      

      【讨论】:

        【解决方案3】:

        根据给定的条件,如果数字是偶数,我们将除以 2,这相当于删除 LSB,如果数字是奇数,我们将减去 1 并使其成为偶数,这相当于取消设置位(将 1 更改为 0)。分析上述过程,我们可以说所需的总步骤数将是(位数,即(log2(n)+1))和设置位数 - 1(不需要删除最后一个 0)的总和。

        C++ 代码:

        result = __builtin_popcount(n) + log2(n) + 1 - 1; result = __builtin_popcount(n) + log2(n);

        【讨论】:

          猜你喜欢
          • 2014-06-09
          • 1970-01-01
          • 2014-01-19
          • 1970-01-01
          • 2016-07-25
          • 1970-01-01
          • 2021-02-24
          相关资源
          最近更新 更多