【问题标题】:Checking for even-odd levels of a min-max heap java检查最小-最大堆java的奇偶级别
【发布时间】:2011-10-11 09:23:27
【问题描述】:

所以这是我编写的一种方法,用于确定数组的给定索引是表示堆的最大级别还是最小级别,其中最小级别具有偶数深度(包括 0),最大级别具有奇数深度。它工作正常,但它的运行时间是(我认为)O(log N)。是否有更有效的方法来执行此操作,例如具有恒定运行时间的简单数学计算?请注意,此方法假定数据从数组的索引 1 开始,而不是索引 0。

    private boolean isMaxLevel(int i)
    {
    int border = 1;
    int prev = 1;
    int count = 1;
    boolean isMax = false;
    // alternates boolean between true and false as each level is checked.
    while (true)
        {
        if (i >= prev && i <= border)
            return isMax;
        isMax = !isMax;
        prev = border + 1;
        count *= 2;
        border += count;
    }
}

【问题讨论】:

    标签: java heap max min depth


    【解决方案1】:

    我不清楚您的要求是什么,但这可能会对您有所帮助。

    public static void main(String... args) {
        for (int i = 1; i <= 256; i *= 2) {
            System.out.println((i - 1) + ": " + isOddHighestBit(i - 1));
            System.out.println(i + ": " + isOddHighestBit(i));
        }
    }
    
    public static boolean isOddHighestBit(int i) {
        return (Double.doubleToRawLongBits(i) >> 52) % 2 == 0;
    }
    

    打印

    0: true
    1: false
    1: false
    2: true
    3: true
    4: false
    7: false
    8: true
    15: true
    16: false
    31: false
    32: true
    63: true
    64: false
    127: false
    128: true
    255: true
    256: false
    

    【讨论】:

    • 你的函数给定输入 (i+1) 将起作用 :) 很好地完成了位移,我不敢相信我没有想到这个日志是基数 2 和所有哈哈. isMaxLevel 会变成:return (Double.doubleToRawLongBits(i+1) &gt;&gt; 52) % 2 == 1; 又快又好 :) 我唯一的问题是为什么 52 位完全被拉黑了?那怎么总是给出最高位?它与它是双而不是长有关吗?
    • double 的最低 52 位是尾数,接下来的 11 位是指数(我们想要的 log2(i))我假设符号是 0(正数)
    • Math.log 相对昂贵。在机器上使用 doubleToRawLongBits 平均耗时 3 ns,使用日志平均耗时 54 ns。
    • 这 54 ns 并不慢,取决于您的频率。 ;)
    • 那个位移解决方案效果很好,但是我将您的解决方案修改为 % == 1 而不是 == 0,就像保罗在他的帖子中所说的那样,所以我不必更改我的解决方案min max heap :) 实际上,我们刚刚开始在我的数据结构类中讨论二进制和十六进制的东西,我们还没有真正讨论过位移,但是教授向我们展示了一个简单的例子。真正看到它像这样应用真的很酷。然而,日志解决方案也很好,让我更多地思考如何解决方程以作为算法的基础。感谢您的回复!
    【解决方案2】:

    我不确定这是否更快,它可能取决于实现,但是:

    private boolean isMaxLevel(int i){
        if(((int)Math.log(i+1)/Math.log(2)))%2 == 1)
            return true;
        return false;
    }
    

    返回正确的值。从数学上考虑。你想找出以下关于 i 的 n 是正确的。如果 n 是奇数,则您有一个最高级别,如果 n 是偶数,您有一个最低级别。

    2ⁿ-1 &lt;= i &lt; 2ⁿ⁺ⁱ-1

    解决这个问题我们得到:

    2ⁿ-1 <= i < 2ⁿ⁺ⁱ-1
    2ⁿ <= i+1 < 2ⁿ⁺ⁱ
    n <= log₂(i+1) < n+1
    n = floor(log₂(i+1))
    

    然后我们可以测试 n 是否为奇数 (n%2 == 1)

    【讨论】:

    • 我真的不认为这会更快...Math.log 比位移慢得多。模数也是如此,它可以用 2 的幂的位移来代替。
    【解决方案3】:

    我们必须检测最小级别和最大级别范围

    1 => pow(2,0) -->最低级别

    2-3 => pow(2,1) 到 pow(2,2)-1 -->最高等级

    4-7 => pow(2,2) 到 pow(2,3)-1 -->最低级别

    8-15 => pow(2,3) 到 pow(2,4)-1 -->最高等级

    c 实现

    #include<math.h>
    #define bool int
    #define true 1
    #define false 0
    int isMinLevel(int i,int n)//i is on min level or not
    {
      int h=2;
      if(i==1)
        return true;
      while(true)
        {
          if(i>=pow(2,h)&&i<=pow(2,h+1)-1)
        return true;
          else if(i>n||i<pow(2,h))
        return false;
          h+=2;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 2020-05-13
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 2011-05-13
      • 1970-01-01
      相关资源
      最近更新 更多