Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
查找数字中连续一位的最大数量(Java)_Java_Algorithm_Performance_Math_Bit - Fatal编程技术网

查找数字中连续一位的最大数量(Java)

查找数字中连续一位的最大数量(Java),java,algorithm,performance,math,bit,Java,Algorithm,Performance,Math,Bit,这实际上是我在书中发现的一个问题。问题是找到一个数字中连续一位的最大数量 例如: 数字123(01111011基数2)应输出“4”(011110){ in=(in&(in您可以将您的递归转换为以获得增强的性能。它对于堆栈使用更节省。如果您不知道尾部递归的含义,请阅读前面的链接 public class ConsecutiveOnes { public static void main(String[] args) { long num = 123;

这实际上是我在书中发现的一个问题。问题是找到一个数字中连续一位的最大数量

例如:

数字123(01111011基数2)应输出“4”(0
1111
<011)

我想找到最有效、最紧凑的算法来实现这一点

这是我最好的机会:

int getMaxBits(long number) {
    return number != 0 ? getMaxBits(number & (number >>> 1)) + 1 : 0;
}
这对小数字非常有效。但由于它可以递归调用它自己多达63次,我认为这不是最有效的方法


我知道,迭代显然效率更高,因为Java编译器不会在没有尾部递归的情况下优化递归。我只是喜欢这样,我可以把它写在一行。真正的问题是,是否有比计算班次更有效的方法?

正如Shawn Chin在中所描述的,这是Java的一个端口:

  public static void count_consecutive_ones(int in) {
      int count = 0;
      while (in>0) {
          in = (in & (in << 1));
          count++;
      }
      System.out.println(count);
  }

  public static void main(String[] args) {
      count_consecutive_ones(15);
  }
公共静态无效计数\u连续\u个(整数英寸){
整数计数=0;
while(in>0){

in=(in&(in您可以将您的递归转换为以获得增强的性能。它对于堆栈使用更节省。如果您不知道尾部递归的含义,请阅读前面的链接

public class ConsecutiveOnes
{
    public static void main(String[] args)
    {
        long num = 123;
        System.out.println(num + " has " + getMaxBits(num) + " consecutive 1's");

    }

    public static int GetMaxBits(long number)
    {
        return accGetMaxBits(number, 0);
    }

    private static int accGetMaxBits(long number, int accum)
    {
        if( number == 0 ) return accum;
        accum += 1;
        return accGetMaxBits(number & (number >>> 1), accum);
    }
}
尝试使用
-1
(长),即
0xFFFFFFFF
,然后将尾部版本与您的版本进行比较

long num = 0xFFFFFFFF;
System.out.println(num + " has " + accGetMaxBits(num) + " consecutive 1's");
// Out: -1 has 64 consecutive 1's

这里有一个明确的方法,即可能有一个更紧凑/高效的实现,但至少可以更直观地理解

count = 0
max = 0
while n > 0
    if first bit (from the right) is 1
        increment count
    else
        if count > max
            max = count
        reset count back to 0
    set n equal to itself right-shifted over 1
return max
在java中:

static int countBits(int n){
int max=0;
整数计数=0;
而(n>0){
如果((n&1)=1)计数++;
否则{
如果(计数>最大值)最大值=计数;
计数=0;
}
如果(计数>最大值)最大值=计数;
n=n>>1;
}
返回最大值;
}
公共静态void main(字符串[]args){
int n=0B1110001111;
系统输出println(countBits(n));
}
输出:

4

    BitSet bitSet = BitSet.valueOf(new long[] {123});
    int count = 0;
    int max = 0;
    for (int i=0; i < bitSet.size(); i++) {
        if(bitSet.get(i)) {
            count++;
        } else {
            max = Math.max(max, count);
            count = 0;
        }
    }
    System.out.println(max);
从表面上看,我的解决方案是丢失的,但如果你有真正的大位数组,它的大小比long的大


p、 欢迎关注代码。

不要使用递归和循环方法?如果递归方法不够优雅,请将其更改为迭代方法。如果long是64位,为什么最大迭代次数不是64?在C中,您可以在(数字&=number-FYI:Hacker's Delight,第二版,第6-3节是关于这个主题的,包含了一些关于这个和相关问题的非常有趣的算法。这个问题是用Java编译的吗?你应该只注释它(链接)/标记为重复then@Bathsheba由于
while(在中)而不会
@Bathsheba no,因为它正在将布尔值转换为long,而我现在没有给出原因。对你和我来说,性能差异很大(即-1(long))。@nickzoum在给出否决票时,请说明原因,不要表现得像个傻瓜,我看起来像个新手吗?(没有否决票(但:),但是:这是如何回答的
[是否有比计算班次更有效的方法?
)我昨天编辑了这个问题。跟踪问题的天数(添加
真正的问题是,是否有比计算班次更有效的方法?
是由nick zoum提出的。)(这是如何回答
[是否有]一种比计算移位更有效的方法?
(问题中的方法:#在最长时间内,而不是像这个答案那样的ld(n)(最高有效位的位置))我的基本假设,以及评论中的一些建议,是,一般来说,迭代解决方案比递归解决方案更有效,因为在递归中,你必须记住以前的函数输入等。而迭代不是这样。所以我的答案,因为它是迭代的,与OP相比,OP是递归的ve可能“更有效”
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@State(Scope.Benchmark)
public class MyBenchmark {

    @Param({"0", "1", "255", "4294967295", "-1"})
    public long value;

    @Benchmark
    public int testBitSet() {
        int count = 0;
        int max = 0;
        BitSet bitSet = BitSet.valueOf(new long[]{value});
        for (int i = 0; i < bitSet.size(); i++) {
            if (bitSet.get(i)) {
                count++;
            } else {
                max = Math.max(max, count);
                count = 0;
            }
        }
        return max;
    }

    @Benchmark
    public int testBitWiseOperation() {
        int max = 0;
        int count = 0;
        while (value > 0) {
            if ((value & 1) == 1) count++;
            else {
                if (count > max) max = count;
                count = 0;
            }
            if (count > max) max = count;
            value = value >> 1;
        }
        return max;
    }

    @Benchmark
    public int testRecursion() {
        return getMaxBits(value);
    }
    public static int getMaxBits(long number) {
        return accGetMaxBits(number, 0);
    }

    private static int accGetMaxBits(long number, int accum) {
        if (number == 0) return accum;
        accum += 1;
        return accGetMaxBits(number & (number >>> 1), accum);
    }
}
# Run complete. Total time: 00:03:49

Benchmark                            (value)  Mode  Cnt   Score   Error  Units
MyBenchmark.testBitSet                     0  avgt    5   3,570 ? 0,019  ns/op
MyBenchmark.testBitSet                     1  avgt    5  84,515 ? 2,188  ns/op
MyBenchmark.testBitSet                   255  avgt    5  85,238 ? 0,581  ns/op
MyBenchmark.testBitSet            4294967295  avgt    5  80,629 ? 0,816  ns/op
MyBenchmark.testBitSet                    -1  avgt    5  66,905 ? 1,446  ns/op
MyBenchmark.testBitWiseOperation           0  avgt    5   2,200 ? 0,297  ns/op
MyBenchmark.testBitWiseOperation           1  avgt    5   2,164 ? 0,011  ns/op
MyBenchmark.testBitWiseOperation         255  avgt    5   2,166 ? 0,030  ns/op
MyBenchmark.testBitWiseOperation  4294967295  avgt    5   2,172 ? 0,047  ns/op
MyBenchmark.testBitWiseOperation          -1  avgt    5   2,164 ? 0,028  ns/op
MyBenchmark.testRecursion                  0  avgt    5   2,171 ? 0,015  ns/op
MyBenchmark.testRecursion                  1  avgt    5   2,460 ? 0,029  ns/op
MyBenchmark.testRecursion                255  avgt    5   9,546 ? 0,090  ns/op
MyBenchmark.testRecursion         4294967295  avgt    5  31,357 ? 0,389  ns/op
MyBenchmark.testRecursion                 -1  avgt    5  66,708 ? 0,349  ns/op