阅读视图

发现新文章,点击刷新页面。

Java Beat 100%

原理:

  1. 使用位运算思想
  2. 假设n=3
    • n=1 二进制为1
    • n=2 二进制为10
    • n=3 二进制为11

假设res为最终结果值,我们一般会想到先将1-n的二进制字符串都求出来然后拼接,再转为十进制,比较暴力。

但其实有更简单的算法,因为,拼接的结果无非是res二进制向左移 $x_i$ 位得到的值与所拼接二进制字符串值的和。
因此,事实上,$x_i$ 的值便是求解的关键。

容易看出,$x_i$ 即为值i表示的二进制字符串的位数,如何求得二进制字符串的位数呢?
类比于十进制,10的整数次幂所表示的值的10进制位数刚好差距为1,如$10^0$,$10^1$,$10^2$,$10^3$
类似的,$2^0$,$2^1$,$2^2$,$2^3$所表示的二进制的位数也刚好差距为1
我们可以利用这一点来求解。
如以n=3为例:
n=1时,二进制为1,res向左移动1位,与1相加,res值为1;
n=2时,二进制为10,res向左移动2位,与2相加,res值为6;
n=3时,二进制为11,res向左移动2位,与3相加,res值为27.

因此,我们只需要判断当前n值是否为为2的幂,如果是,位数偏移在之前的基础上加1,否则位数偏移不变
判断n值是否为2的幂方法有很多,在这里我采用了一种比较简单的方法i & (i-1)是否等于0,如果i是2的幂,说明仅某一位为1,其余均为0,那么i-1即为其余位均为1,自然与运算为0。如果难以理解可以想象99和100的关系。

下面是全部代码:

###java

public class Solution {
    private static final int MOD = 1000000007;

    public int concatenatedBinary(int n) {
        int res = 0, shift = 0;
        for (int i = 1; i <= n; i++) {
            if ((i & (i - 1)) == 0) {
                // 说明是2的幂,则进位
                shift++;
            }
            res = (int) ((((long) res << shift) + i) % MOD);
        }
        return res;
    }
}
❌