添加从1到N的所有数字,其设置位数为2

时间:2015-11-28 20:41:24

标签: java algorithm

我有一个问题,我必须添加从1到N的数字,其设置位为2.对于N = 5,我们应该得到值8,因为数字3和5有2位设置为1。我在java中实现了相同的功能。我得到的o / p对于int值是正确的,但是当涉及到长值时,要么花费大量时间或冻结,当我在代码判断网站上提交相同内容时,它就是给运行时间超出消息。请指导我如何优化我的代码以更快地运行它,谢谢:)

public static void main(String[] args)
{
    long n = 1000000L;
    long sum = 0;
    long start = System.currentTimeMillis();
    for(long i = 1L ; i <= n ; i++)
    {
        if(Long.bitCount(i) == 2)
        {
            sum += i;
        }
    }
    long end = System.currentTimeMillis();
    System.out.println(sum);
    System.out.println("time="+(end-start));
}

4 个答案:

答案 0 :(得分:1)

正如@hbejgel指出的那样,循环所有数字并检查其位数是没有意义的。您可以简单地构造2位数字并将它们相加。

你可以通过在long中选择两个不同的位位置来构造一个2位的数字,&#34;更高的&#34; bit和&#34; lower&#34;位&#34;:

long i = (1 << higher) + (1 << lower);

因此,您可以简单地遍历所有这些数字,直到您构建的值超出限制:

long sum = 0;
outer: for (int higher = 1; higher < 63; ++higher) {
  for (int lower = 0; lower < higher; ++lower) {
    long i = (1 << higher) + (1 << lower);
    if (i <= n) {
      sum += i;
    }
    if (i >= n) break outer;
  }
}

答案 1 :(得分:0)

假设我们知道最接近的数字x,等于或低于N且有2个设定位,那么我们可以使用幂系列的公式快速求和两组的所有位置比特,例如,如果x = b11000,我们求和

  4*2^0 + S(4)
+ 3*2^1 + S(4) - S(1)
+ 2*2^2 + S(4) - S(2)
+ x

where S(n) = 2 * (1 - 2^n) / (1 - 2) 
           = 2 + 2^2 + 2^3 ... + 2^n

答案 2 :(得分:0)

对于编号为2 out of 5的数字,每个一位数字中都设置了两位。总和为45,但N×(N-1)/2除外,0≤N <9。

答案 3 :(得分:0)

我认为问题应该是发现模式。

  1. 快进。给定数字N,您可以说出最大的数字 应该从前两位的位掩码计数。所以你有了 较小的数字M

  2. 跳到下一个计数的数字给定任意两位设置的数字,下一个 最大的数字是第二个位移一个,直到下溢。

  3. 跳到下一个顺序当第二组发生下溢时,移动 一点一点,也就是右边的一点。

  4. 你真的不需要N上的循环,但它有它的位。

    下一个问题:你能回答多少?其中N> 100,000,000

    下一个下一个问题:当X> 2

    时,你能回答X位的相同问题吗?