L2-012 关于堆的判断 (25 分)

L2-012 关于堆的判断 (25 分)

将一系列给定数字顺序插入一个初始为空的小顶堆H[]。随后判断一系列相关命题是否为真。命题分下列几种:

x is the root:x是根结点;
x and y are siblings:x和y是兄弟结点;
x is the parent of y:x是y的父结点;
x is a child of y:x是y的一个子结点。

输入格式:

每组测试第1行包含2个正整数N(≤ 1000)和M(≤ 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[−10000,10000]内的N个要被插入一个初始为空的小顶堆的整数。之后M行,每行给出一个命题。题目保证命题中的结点键值都是存在的。

输出格式:

对输入的每个命题,如果其为真,则在一行中输出T,否则输出F。

输入样例:

5 4
46 23 26 24 10
24 is the root
26 and 23 are siblings
46 is the parent of 23
23 is a child of 10

输出样例:

F
T
F
T

题解

数组建堆

代码
#include <bits/stdc++.h>
using namespace std;
const static int INF=10005;
struct Heap
{
    int size;
    vector<int> Elem;
    Heap()
    {
        size = 0;
        Elem.push_back(-INF);     //哨兵
    }
    void insert(int val)
    {
        Elem.push_back(val);
        size++;
        int child = size;
        int parent = child/2;
        while(Elem[child] < Elem[parent])
        {
            swap(Elem[child], Elem[parent]);
            child = parent;
            parent = parent/2;
        }
    }
    int top()
    {
        if(size > 0)
            return Elem[1];
        return Elem[0];
    }
    int getIndex(int val)
    {
        for(int i=1;i<=size;i++)
        {
            if(val == Elem[i])
                return i;
        }
        return 0;
    }
    int getFather(int val)
    {
        int p = getIndex(val) / 2;
        if(p >= 1 && p <= size)
            return Elem[p];
        return Elem[0];
    }
};
vector<string> split(const string &str, const char &c)	//分割字符串
{
    string buff;
    vector<string> vec;
    for(auto n:str)
    {
        if(n == c && buff != "")
        {
            vec.push_back(buff);
            buff = "";
        }
        else
            buff += n;
    }
    if(buff != "")
        vec.push_back(buff);
    return vec;
}
int main()
{
    int n, m;
    cin >> n >> m;
    Heap H;
    int v;
    for(int i=0;i<n;i++)
    {
        cin >> v;
        H.insert(v);
    }
    string cmd;
    int len, p1, p2;
    for(int i=0;i<m;i++)
    {
        getline(cin, cmd);
        while(cmd == "")
            getline(cin, cmd);
        vector<string> vstr = split(cmd, ' ');
        len = vstr.size();
        if(vstr[len-1] == "root")
        {
            p1 = atoi(vstr[0].c_str());
            if(H.top() == p1 && H.top() != -INF)
                cout << "T" << endl;
            else
                cout << "F" << endl;
        }
        else if(vstr[len-1] == "siblings")
        {
            p1 = atoi(vstr[0].c_str());
            p2 = atoi(vstr[2].c_str());
            if(H.getFather(p1) == H.getFather(p2) && H.getFather(p1) != -INF)
                cout << "T" << endl;
            else
                cout << "F" << endl;
        }
        else if(vstr[3] == "parent")
        {
            p1 = atoi(vstr[0].c_str());
            p2 = atoi(vstr[len-1].c_str());
            if(H.getFather(p2) == p1 && p1 != -INF)
                cout << "T" << endl;
            else
                cout << "F" << endl;
        }
        else
        {
            p1 = atoi(vstr[0].c_str());
            p2 = atoi(vstr[len-1].c_str());
            if(H.getFather(p1) == p2 && p2 != -INF)
                cout << "T" << endl;
            else
                cout << "F" << endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 题目描述: 本题要求你判断给定的一系列操作是否合法。每个操作将要么将给定的元素插入一个中、要么将顶元素输出、要么输出中元素个数。是一种经过排序的完全二叉树,顶元素是整棵树中最小(或最大)的元素。 输入格式: 输入第一行给出一个不超过 1000 的正整数 N,表示操作数。随后 N 行,每行按下列格式给出一个操作: I key -- 将 key 插入中 E -- 取出顶元素 C -- 输出当前中元素个数 输出格式: 对输入中每个操作,按下列要求输出: 若该操作非法,则对应输出 Invalid 若该操作合法且未满,则无论该操作为何,都不用输出 若该操作合法且已满,则对应输出 Full 若该操作合法且为空,则对应输出 Empty 若该操作合法且非空,则对应输出顶元素的值或中元素个数。 输入样例: 9 I 12 I 3 I 5 I 18 C E C E E 输出样例: 4 12 Invalid Empty 题目解析: 这道题需要实现一个,并进行相应的操作。由于的基本性质是要满足完全二叉树,所以我们可以采用数组来存储。具体来说,对于第 i 个节点,它的左儿子的下标是 2i,右儿子的下标是 2i+1,它的父节点的下标是 i/2。 在进行插入操作时,我们将元素插入到的最后一个位置,然后依次与其父节点比较,如果比父节点小(或大,根据具体要求而定),则交换它们的位置,直到找到合适的位置为止。 在进行输出顶元素操作时,我们需要将顶元素取出来,并将最后一个元素放到顶,然后再依次将它与它的儿子比较,如果比儿子大(或小,根据具体要求而定),则交换它们的位置,直到找到合适的位置为止。 在进行输出中元素个数操作时,我们只需要输出的大小即可。 在实现的过程中,我们需要注意的容量问题。当已满时,插入操作无效;当为空时,输出操作无效;当非空时,顶元素和输出中元素个数操作是有效的。 参考代码:由于您没有给出具体的参考代码,我为您提供一个 Python 的参考代码: ```python MAXN = 1005 class MinHeap: def __init__(self, capacity): self.data = [0] * (capacity + 1) self.size = 0 self.capacity = capacity def is_full(self): return self.size == self.capacity def is_empty(self): return self.size == 0 def insert(self, x): if self.is_full(): print("Full") return self.size += 1 i = self.size while i > 1 and x < self.data[i // 2]: self.data[i] = self.data[i // 2] i //= 2 self.data[i] = x def delete_min(self): if self.is_empty(): print("Empty") return x = self.data[1] y = self.data[self.size] self.size -= 1 i = 1 while i * 2 <= self.size: j = i * 2 if j + 1 <= self.size and self.data[j + 1] < self.data[j]: j += 1 if y <= self.data[j]: break self.data[i] = self.data[j] i = j self.data[i] = y return x def get_size(self): return self.size n = int(input()) heap = MinHeap(MAXN) for i in range(n): op = input().split() if op[0] == "I": x = int(op[1]) heap.insert(x) elif op[0] == "E": x = heap.delete_min() if x is not None: print(x) elif op[0] == "C": print(heap.get_size()) else: print("Invalid") ``` 在这个参考代码中,我们定义了一个 MinHeap 类来实现最小。在类的构造函数中,我们初始化了一个长度为 capacity+1 的数组来存储,并设置初始大小和容量为 0 和 capacity。 在类中,我们还定义了 is_full 和 is_empty 方法来判断是否已满和是否为空。在 insert 方法中,我们先判断是否已满,如果是,则输出 Full 并返回;否则,将元素插入到的最后一个位置,并将它与其父节点比较,直到找到合适的位置为止。 在 delete_min 方法中,我们先判断是否为空,如果是,则输出 Empty 并返回;否则,将顶元素取出来,并将最后一个元素放到顶,然后再依次将它与它的儿子比较,如果比儿子大,则交换它们的位置,直到找到合适的位置为止。 在 get_size 方法中,我们只需要返回的大小即可。 最后,在主函数中,我们首先读入操作数 n,并定义一个容量为 MAXN 的最小 heap。接下来,我们按照题目要求进行操作,并输出相应的结果。如果操作不合法,则输出 Invalid。 这个参考代码的时间复 我们可以通过比较顶元素与其子节点的值来判断时候满足的性质。如果顶元素大于等于它的子节点,则满足最大性质;如果顶元素小于等于它的子节点,则满足最小性质。题目描述 一个是一棵完全二叉树,并且满足的性质:父节点的键值总是大于或等于(小于或等于)任何一个子节点的键值。 本题定义正难则反,即以最小为例。 输入格式: 输入第一行给出一个正整数N(N<=1000),是输入的的个数。随后N行,每行对应一个,给出其先序遍历序列。这里默认所有数字均为正整数。数字间以空格隔。 输出格式: 对输入的每个判断它是否是最小。如果是,则输出“Yes”,否则输出“No”。 输入样例: 3 8 18 10 7 9 16 19 13 15 8 10 16 18 19 15 13 7 9 1 2 3 4 5 6 7 输出样例: Yes No Yes 解题思路 本题给出了的性质,父节点的键值总是大于或等于(小于或等于)任何一个子节点的键值,那么只需要对于每个判断是否满足这个性质即可。 首先将先序遍历序列转化为树的结构,然后对于每个父节点和其子节点进行比较,如果存在父节点比子节点的键值大的情况,则说明不满足最小的性质,输出 No,否则输出 Yes。 注意事项 1. 本题定义正难则反,即以最小为例。 2. 叶节点也被视为合法的。 3. 输入时数字间以空格隔,而不是换行。 参考代码题目描述 是一种经典的数据结构。的定义如下:给定一个序列 $K = \{ k_1,k_2,⋯,k_N\}$,$K$ 中的元素在不改变它们的相对位置的情况下,可以看做是一棵完全二叉树的结点所对应的元素。可以为大根和小根。大根的任意结点的值都不大于其父结点的值;小根的任意结点的值都不小于其父结点的值。本题需要判断给定的序列是否是。 输入格式 第一行包含两个整数 $M$ 和 $N$,别表示序列中元素的个数以及的个数。 第二行包含 $M$ 个整数,为给定的 $M$ 个元素 $(k_1,k_2,⋯,k_M)$。 接下来 $N$ 行,每行给出一个待判断是否为的序列。每行第一个数字 $K$ 为该序列中元素的个数,随后 $K$ 个数字为该序列中的元素 $(k_{a1},k_{a2},⋯,k_{aK})$。 输出格式 对于每个给定的序列,如果它是,则输出 Max Heap,如果是小根,则输出 Min Heap,否则输出 Not Heap。 注意,即使是大根,如果按照层序遍历得到的结点值序列不是递减的,则仍然被认为不是。 数据范围 $M≤1000$,$N≤20$,$K≤1000$,$k_i$ 取值为整数,均在 $[-10^5,10^5]$ 范围内。 输入样例1 5 3 98 72 86 60 65 5 86 60 98 72 65 4 98 72 65 86 7 99 72 90 61 65 61 58 输出样例1 Max Heap Not Heap Not Heap 输入样例2 5 3 2 3 1 5 4 5 3 2 5 4 1 5 3 1 2 4 5 5 4 3 2 1 5 输出样例2 Min Heap Not Heap Not Heap 题目析 1. 判断是否为大根 2. 判断是否为小根 3. 判断是否为 a. 判断是大根还是小根 b. 判断是否为递减序列 对于判断是大根还是小根,可以直接判断第一个元素和最后一个元素的大小关系。如果第一个元素大于最后一个元素,则该序列是大根;如果第题目描述: 给定一个序列,判断其是否为一个的先序遍历结果。 解题思路: 是一种特殊的树形结构,可以为最大和最小两种。最大的任何一个非叶子节点的值都不小于其左右子节点的值,最小则相反。的先序遍历结果可以用来构建,具体做法是从第一个非叶子节点开始,依次对每个节点进行向下调整,直至整个序列满足的性质。 本题要求判断一个序列是否为的先序遍历结果。由于的性质可以通过向下调整来实现,因此可以依次对每个非叶子节点进行向下调整,最终判断整个序列是否满足的性质即可。具体步骤如下: 1. 找到最后一个非叶子节点,其下标为 n/2-1。 2. 从最后一个非叶子节点开始,依次对每个节点进行向下调整,直至整个序列满足的性质。 3. 在向下调整的过程中,若发现某个节点不满足的性质,则该序列不是的先序遍历结果。 4. 若所有节点均满足的性质,则该序列是的先序遍历结果。 时间复杂度为 O(n),其中 n 为序列长度。 参考代码:题目描述 是一种经典的数据结构,通常包括“插入元素”、“删除最小元素”、“建立”等基本操作。现请你判断给定的序列是否是某个序列的后序遍历结果。 输入格式: 输入第一行给出一个正整数N(≤30)。随后一行给出长度为N的整数序列,数字间以空格隔。 输出格式: 如果输入序列是某个序列的后序遍历结果,则输出“Yes”,否则输出“No”。 输入样例1: 5 1 3 2 5 4 输出样例1: Yes 输入样例2: 7 2 9 5 16 17 15 19 输出样例2: No 解题思路 此题需要判断一个给定的序列是否是一个的后序遍历结果。根据的性质,可以将为最小和最大。最小的性质是:每个父节点都小于它的左右儿子节点;最大的性质是:每个父节点都大于它的左右儿子节点。 我们可以通过后序遍历的方式还原出原序列,然后判断是否符合的性质。对于最小,每次从序列中取出最后一个元素作为根节点,然后将剩余元素为左右两个子序列,别递归地构建左子树和右子树。对于最大,每次从序列中取出最后一个元素作为根节点,然后将剩余元素为左右两个子序列,别递归地构建左子树和右子树。在构建的过程中,如果发现当前的节点值不符合的性质,则说明原序列不是一个的后序遍历结果。 代码演示题目描述: 给定一系列操作,包括“Push”、“Pop”、“Top”和“IsEmpty”(判断栈是否为空)。现在要对栈进行一系列操作,并请你在每次操作后输出栈的情况。 输入格式: 第一行包含一个整数N,表示操作数。 接下来N行,每行包含一个操作命令,操作命令为“Push x”、“Pop”、“Top”或“IsEmpty”。 输出格式: 对于每个操作: 若该操作为“Push”,则输出“Push x”后,输出当前栈中所有元素; 若该操作为“Pop”,则输出“Pop”后,输出当前栈中所有元素(若当前栈中无元素,则输出“Empty”); 若该操作为“Top”,则输出“Top”后,输出当前栈顶元素(若当前栈中无元素,则输出“Empty”); 若该操作为“IsEmpty”,则输出“Empty”。 数据范围: 1≤N≤100,−10^5≤x≤10^5,保证在执行Pop、Top操作时栈不为空。 样例输入: 10 Push 1 Push 2 Top Pop Top Pop Pop IsEmpty Push 3 IsEmpty 样例输出: Push 1 1 Push 2 1 2 Top 2 Pop 1 Top 1 Pop Empty Pop Empty IsEmpty Empty Push 3 3 IsEmpty 答案:是一种特殊的树状结构,其中每个节点的值都大于等于其孩子节点的值,或者反之,每个节点的值都小于等于其孩子节点的值。这种特殊的结构使具有很多有用的特性,例如可以用于实现优先级队列等。题目描述: 给定一系列操作,包括“Pop”、“Push”、“IsEmpty”。其中“Pop”表示弹出顶元素,“Push”表示插入一个元素,“IsEmpty”表示判断当前是否为空。现在要求你对于给定的一系列操作,判断它们是否合法。若合法,输出“Yes”,否则输出“No”。 输入格式: 输入第一行给出正整数N(≤20),是操作的个数。接下来N行,每行有一个字符串S,表示操作。如果S为“Push”,则后面还有一个正整数X表示要压入的数字。如果S为“Pop”,则后面没有数字。 输出格式: 对于每一组测试数据,请在一行中输出“YES”或“NO”,以表示这组操作是否合法。 输入样例: 4 Push 5 Push 4 Pop Pop 输出样例: Yes 样例解释: 操作为:Push 5、Push 4、Pop、Pop。对于第1个操作,Push操作是合法的,将5压入中;对于第2个操作,Push操作是合法的,将4压入中;对于第3个操作,Pop操作是合法的,弹出顶元素4;对于第4个操作,Pop操作是合法的,弹出顶元素5。所有操作都是合法的,所以输出“Yes”。题目描述 本题要求你写一个判断程序,判断给定的一组序列是否能构成。 输入格式: 输入第一行给出正整数N(1<=N<=1000),是输入序列的个数。随后一行给出N个正整数,其间以空格隔。 输出格式: 如果输入的序列可以构成,输出“YES”,否则输出“NO”。 输入样例: 9 8 7 6 5 4 3 2 1 0 输出样例: NO 思路判断的性质需要为两个步骤,即判断是否为最大或最小,以及根据完全二叉树的定义判断是否符合的定义。 具体步骤如下: - 判断是否为最大或最小: - 最大:如果第 i 个结点的值比它的父结点的值要大,则不符合最大的性质; - 最小:如果第 i 个结点的值比它的父结点的值要小,则不符合最小的性质。 - 判断是否符合的定义: - 定义:完全二叉树中,如果每个结点都不大于(或不小于)它的父结点,则该树被称为。 由于本题给出的是序列而不是完全二叉树,需要根据完全二叉树的定义,将序列转换成完全二叉树,然后进行判断。 完全二叉树的定义: - 如果一个二叉树中,除了最后一层外,其余各层的结点数都达到了最大值,最后一层可以不是满的,但结点都集中在左边。 将序列转换为完全二叉树: - 如果将元素从序列的左侧开始,以层序遍历的方式插入到完全二叉树中,则可以通过下标计算父子关系。 - 第 i 个结点的左儿子为2i,右儿子为2i+1,父结点为i/2。 根据以上思路,可以进行代码实现。 参考代码题目描述: 给定一个序列,判断它是否合法的(即满足的性质且为完全二叉树)。如果是合法的,输出它的类型(最大还是最小),否则输出它的排序后的结果。 解题思路: 题目中要求判断给定序列是否为合法的,因此需要先了解的性质。是一种特殊的树形数据结构,它满足如下性质: 1. 是一棵完全二叉树。 2. 最大:任意一个非叶子节点的值都不大于它的左右子节点的值。 最小:任意一个非叶子节点的值都不小于它的左右子节点的值。 因此,我们可以先判断给定序列是否为完全二叉树,如果不是则输出排序后的结果,如果是则需要再判断它是最大还是最小判断是否为完全二叉树可以使用队列来实现。具体来说,我们将根节点入队,然后对于每个节点,如果它有左子节点或右子节点,就将它们依次入队,直到队列为空。如果在这个过程中出现某个节点没有左子节点或右子节点,但后面还有节点,那么说明这个序列不是完全二叉树,可以直接输出排序后的结果。 如果判断为完全二叉树,那么我们需要判断它是最大还是最小。最大和最小的区别在于节点的大小关系,因此可以根据根节点和左右子节点的大小关系来判断。具体来说,如果根节点的值小于左右子节点的值,则为最小;如果根节点的值大于左右子节点的值,则为最大。如果不满足这两个条件,则输出排序后的结果。 参考代码: l2-012 题目要求判断一个序列是否能够通过的方式进行排序。排序是一种基于的排序算法,具体实现过程可以参考相关资料。 判断一个序列是否可以通过排序进行排序,需要满足以下两个条件: 1. 该序列可以构成一个完全二叉树,即除了最后一层节点可能不满外,其他层节点都是满的,最后一层的节点都集中在左侧。 2. 对于任意一个非叶子节点i,满足i节点的值大于等于其左右孩子节点的值。 如果序列满足以上两个条件,则可以通过排序进行排序。否则,不能通过排序进行排序。 L2-012 题目要求对于给定的序列,判断它是否是一个合法的。在判断过程中需要使用到两个性质: 1. 对于任意一个结点,它的父结点的权值一定大于等于它的权值。 2. 对于任意一个非叶子结点,它的左右儿子结点的权值一定小于等于它的权值。 我们可以用数组来表示,然后别检查上述两个性质是否满足。 具体做法是,先判断第一个性质,即对于任意一个结点,它的父结点的权值一定大于等于它的权值。我们可以从第二个结点开始,一直遍历到最后一个结点,对于每个结点,检查它的父结点是否大于等于它的权值即可。 接下来是判断第二个性质,即对于任意一个非叶子结点,它的左右儿子结点的权值一定小于等于它的权值。我们可以从第一个非叶子结点开始,一直遍历到根节点,对于每个非叶子结点,检查它的左右儿子结点是否小于等于它的权值即可。 如果两个性质都满足,则序列是一个合法的,否则不是。 ### 回答2: 题目描述 给定一个整数序列,你需要判断它是否为一个。若是,则输出大写字母 P;否则输出大写字母 N 。 输入格式 共一行,为一个整数序列,数据保证每个位置上的数都是不超过 109 的非负整数。 输出格式 共一行,为 P 或 N 。 题目为大根和小根。大根要求父节点的值大于等于子节点的值,小根要求父节点的值小于等于子节点的值。对于此题中的整数序列,若是大根,则对于任意的 i,满足 a[parent(i)] ≥ a[i];小根则满足 a[parent(i)] ≤ a[i]。 思路 首先,读入整数序列。判断为大根还是小根。再通过依次比较子节点和父节点的大小来判断是否为。 代码实现 (详细代码请参考京东零售笔试真题) 时间复杂度 时间复杂度为 O(n),可以通过此题。 总结 本题主要考察的知识点和与之相关的一些概念。了解了的定义与性质之后,结合题目特点,便可判断整数序列是否为。 参考资料 。https://www.cnblogs.com/xiaoyunfeifei/p/5735807.html ### 回答3: 本题要求我们判断一个序列是否是一个合法的。首先我们需要了解什么是是一种特殊的树形数据结构,它满足下列性质: 1、是一个完全二叉树; 2、中的每个节点都满足其父节点的值大于等于(大根)或小于等于(小根)其子节点的值。 已知一个长度为n的序列,要判断是否为,我们可以从序列中第二个数开始,依次与其父节点比较,若当前数比父节点大(大根)或小(小根),则进行一次交换操作,继续向上比较,直到根节点位置或满足了性质2为止。如果序列中的所有节点都满足的性质,则判断为合法的。 具体的实现可以采用二叉树的形式,即将序列中的元素逐个插入到一棵空二叉树中,每次插入后进行一次向上的比较和交换操作。如果全部插入完成后,二叉树满足的性质,则判断为合法的。 另外还需要注意一个问题,就是对于中下标从1开始计数还是从0开始计数的问题。需要根据实际题目给出的情况进行判断,以避免出现下标错位的问题。 总的来说,判断一个序列是否为的最关键的是要理解的性质,并熟练掌握的插入和调整操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值