是最大堆吗?


14

,也被称为优先级的队列,是一个抽象的数据类型。从概念上讲,它是一个二叉树,其中每个节点的子代小于或等于节点本身。(假定它是一个最大堆。)当元素被推入或弹出时,堆会重新排列自身,因此最大的元素是下一个要弹出的元素。它可以很容易地实现为树或数组。

您应该选择接受的挑战是,确定数组是否为有效堆。如果每个元素的子元素小于或等于元素本身,则该数组为堆形式。以以下数组为例:

[90, 15, 10, 7, 12, 2]

实际上,这是一个以数组形式排列的二叉树。这是因为每个元素都有孩子。90岁有两个孩子15和10。

       15, 10,
[(90),         7, 12, 2]

15岁还有7岁和12岁的孩子:

               7, 12,
[90, (15), 10,        2]

10个有孩子:

                      2
[90, 15, (10), 7, 12,  ]

而下一个元素也将是10的孩子,除了没有空间。如果数组足够长,则7、12和2也都将有子级。这是堆的另一个示例:

[16, 14, 10, 8, 7, 9, 3, 2, 4, 1]

这是先前数组制作的树的可视化效果:

在此处输入图片说明

以防万一这还不够清楚,这是获取第i个元素的子元素的显式公式

//0-indexing:
child1 = (i * 2) + 1
child2 = (i * 2) + 2

//1-indexing:
child1 = (i * 2)
child2 = (i * 2) + 1

您必须采用非空数组作为输入,并且如果该数组按堆顺序输出,则必须输出真实值,否则必须输出伪值。只要指定程序/函数期望的格式,它就可以是0索引堆或1索引堆。您可以假设所有数组仅包含正整数。您不能使用任何堆内置的。这包括但不限于

  • 确定数组是否为堆形式的函数
  • 将数组转换为堆或堆形式的函数
  • 将数组作为输入并返回堆数据结构的函数

您可以使用此python脚本来验证数组是否为堆形式(索引为0):

def is_heap(l):
    for head in range(0, len(l)):
        c1, c2 = head * 2 + 1, head * 2 + 2
        if c1 < len(l) and l[head] < l[c1]:
            return False
        if c2 < len(l) and l[head] < l[c2]:
            return False

    return True

测试IO:

所有这些输入都应返回True:

[90, 15, 10, 7, 12, 2]
[93, 15, 87, 7, 15, 5]
[16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
[100, 19, 36, 17, 3, 25, 1, 2, 7]
[5, 5, 5, 5, 5, 5, 5, 5]

所有这些输入都应返回False:

[4, 5, 5, 5, 5, 5, 5, 5]
[90, 15, 10, 7, 12, 11]
[1, 2, 3, 4, 5]
[4, 8, 15, 16, 23, 42]
[2, 1, 3]

像往常一样,这是代码高尔夫球,因此存在标准漏洞,并且以字节为单位的最短答案为胜!



如果存在重复的元素,根据该定义可能无法形成堆是否正确?
feersum'7

@feersum怎么样[3, 2, 1, 1]
Neil

@feersum太好了,我没想到。我更新了堆的描述,并添加了一些带有重复元素的示例。谢谢!
詹姆斯

5
堆也称为优先级队列。优先级队列是抽象数据类型。堆是有时用于实现优先级队列的数据结构(堆本身是在更多基础数据结构之上实现的,但这并不重要)。可以在其他数据结构(例如链表)的顶部实现优先级队列。
Lyndon White

Answers:


7

果冻, 11 9 5字节

x2:ḊṂ

多亏了丹尼斯,删除了4个字节!

在这里尝试。

说明

x2          Duplicate each element.
:Ḋ          Each element divided by the input with the first element removed,
            as integer, so there is a 0 only if some element in the duplicated
            list is less than the corresponding element in the other.
            There are also elements left unchanged, but it doesn't matter as
            the input is all positive.
Ṃ           Minimum in the list.

10

JavaScript(ES6),34个 30字节

a=>!a.some((e,i)=>e>a[i-1>>1])

编辑:修复我的规范说明代码花费了1个字节,因此感谢@ edc65节省了4个字节。


它无法通过测试用例2 [93, 15, 87, 7, 15, 5]和6[5, 5, 5, 5, 5, 5, 5, 5]
edc65 '16

这样效果更好,短了3个字符a=>!a.some((e,i)=>e>a[i-1>>1])
edc65 '16

1
@ edc65这些测试用例是在我写下答案后添加的。
尼尔


4

J,24个字节

*/@:<:]{~0}:@,<.@-:@i.@#

说明

*/@:<:]{~0}:@,<.@-:@i.@#  Input: s
                       #  Count of s
                    i.@   Create range [0, 1, ..., len(s)-1]
                 -:@      Halve each
              <.@         Floor each
         0   ,            Prepend a zero to it
          }:@             Remove the last value to get the parent indices of each
      ]                   Identity function to get s
       {~                 Take the values from s at the parent indices
    <:                    For each, 1 if it is less than or equal to its parent else 0
*/@:                      Reduce using multiplication and return

3

MATL13 12字节

ttf2/k)>~4L)

在线尝试!验证所有测试用例

如果数组为非空且其所有条目均为非零,则为真。否则是虚假的。这里有一些例子

说明

t     % Take input implicitly. Duplicate
tf    % Duplicate and push indices of nonzero entries. This gives [1 2 ... n] where n
      % is input size
2/k   % Divide by 2 and round down
)     % Index into input. Gives array of parents, except for the first entry
>~    % True for entries of the input that don't exceed those in the array of parents
4L)   % Discard first entry

2

Python 2,45个字节

f=lambda l:l==[]or l[len(l)/2-1]/l.pop()*f(l)

对于Falsy输出0,对于Truthy输出非零。

检查最后一个元素是否小于或等于其在index处的父元素len(l)/2-1。然后,递归检查列表的最后一个元素是否被删除,以此类推,直到列表为空。


48个字节:

f=lambda l,i=1:l==l[:i]or l[~-i/2]/l[i]*f(l,i+1)

检查在每个索引处i,元素最多是否是其在索引处的父元素(i-1)/2。如果不是这种情况,则楼层划分产生0。

进行与基本情况i/len(l)or相同的长度。我起初尝试压缩,但是获得了更长的代码(57个字节)。

lambda l:all(map(lambda a,b,c:b<=a>=c,l,l[1::2],l[2::2]))

1

R,97 88 82字节

希望我已经正确理解了这一点。现在来看我是否可以摆脱更多的字节。抛开框线,并适当地处理基于1的向量。

实现为未命名函数

function(Y)all(sapply(1:length(Y),function(X)Y[X]>=Y[X*2]&Y[X]>=Y[X*2+1]),na.rm=T)

有一些测试用例

> f=
+ function(Y)all(sapply(1:length(Y),function(X)Y[X]>=Y[X*2]&Y[X]>=Y[X*2+1]),na.rm=T)
> f(c(90, 15, 10, 7, 12, 2))
[1] TRUE
> f(c(93, 15, 87, 7, 15, 5))
[1] TRUE
> f(c(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
[1] TRUE
> f(c(5, 5, 5, 5, 5, 5, 5, 5))
[1] TRUE
> f(c(4, 5, 5, 5, 5, 5, 5, 5))
[1] FALSE
> f(c(90, 15, 10, 7, 12, 11))
[1] FALSE
> f(c(4, 8, 15, 16, 23, 42))
[1] FALSE

您可以使用seq(Y)代替1:length(Y)
rturnbull




0

C ++ 14,134个 105字节

#define M(d) (2*i+d<c.size()&&(c[i]<c[2*i+d]||f(c,2*i+d)==0))
int f(auto&c,int i=0){return!(M(1)||M(2));}

要求c是一个容器支撑.operator[](int).size(),等std::vector<int>

取消高尔夫:

int f(auto& c, int i=0) {
    if (2*i+1<c.size() && c[i] < c[2*i+1]) return 0;
    if (2*i+2<c.size() && c[i] < c[2*i+2]) return 0;
    if (2*i+1<c.size() && (f(c,2*i+1) == 0)) return 0;
    if (2*i+2<c.size() && (f(c,2*i+2) == 0)) return 0;
    return 1;
}

如果允许truey 0和falsy =,则可以较小1


0

R,72个字节

与其他R回答略有不同。

x=scan();all(diff(x[c(a<-1:(N<-sum(1|x)),a,a*2,a*2+1)],l=N*2)<1,na.rm=T)

从stdin读取输入,创建所有比较对的向量,将它们彼此相减,然后检查结果是否为负数或零。

说明

从stdin读取输入:

x=scan();

创建我们的对。我们为父节点创建的索引1...N(其中N的长度为x)。我们将其作为两次,因为每个父母(最多)有两个孩子。我们还带孩子,(1...N)*2并且(1...N)*2+1。对于长度超过的索引x,R返回NA,“不可用”。对于输入90 15 10 7 12 2,此代码给了我们90 15 10 7 12 2 90 15 10 7 12 2 15 7 2 NA NA NA 10 12 NA NA NA NA

                  x[c(a<-1:(N<-sum(1|x)),a,a*2,a*2+1)]

在此对向量中,每个元素在相距较远的N*2地方都有其伙伴。例如,项目1的伙伴位于位置12(6 * 2)。我们用于diff计算这些对之间的差异,指定lag=N*2将项目与其正确的合作伙伴进行比较。对NA元素的任何操作都只返回即可NA

             diff(x[c(a<-1:(N<-sum(1|x)),a,a*2,a*2+1)],l=N*2)

最后,我们检查所有返回的值是否都小于1(即,第一个数字(父级)大于第二个数字(子级)),不NA考虑值。

         all(diff(x[c(a<-1:(N<-sum(1|x)),a,a*2,a*2+1)],l=N*2)<1,na.rm=T)

0

实际上,16个字节

该答案主要基于jimmy23013的Jelly答案。欢迎打高尔夫球!在线尝试!

;;2╟┬Σ1(tZ`i<`Mm

开球

         Implicit input a.
;;       Duplicate a twice.
2╟       Wrap two of the duplicates into a list.
┬        Transpose the duplicates.
Σ        Sum all of the columns to get a flat list like this:
           [a_0, a_0, a_1, a_1, ..., a_n, a_n]
         This gets the parent nodes of the heap.
1(t      Get a[1:] using the remaining duplicate of a.
         This is a list of the child nodes of the heap.
Z`i<`M   Check if every child node is less than its parent node.
m        Get the minimum. This returns 1 if a is a max-heap, else 0.
         Implicit return.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.