PAT 1051-1060 题解

浏览全部代码:请戳

本文谨代表个人思路,欢迎讨论;)

1051. Pop Sequence (25)

题意

给定 stack 的容量,给定数据的入栈顺序:从 1 开始的正整数序列,在允许随机的出栈操作的情况下,要求判断某出栈序列是否可能。

比如,告知 stack 容量为 5,入栈序列的最大值为 7。有两个序列需要判断合理性:

  • {1 2 3 4 5 6 7}: 这个序列是可能的,只需每次入栈时都做出栈操
  • {3 2 1 7 5 6 4}: 这个序列是不可能的,其中前半部分3 2 1是合法的,先将1 2 3顺序入栈,然后三次执行出栈操作。而之后的7 5 6则是不可能的。

分析

两种思路:

第1种思路:

使用stl中的stack模拟。判定条件有两条:1.栈中数据量不超过栈的容量;2.出栈只能从栈顶取,不应该出现从固定的堆栈中取出其他数据的情况。

第2种思路:

由于入栈序列数据由小到大排列非常特殊,要通过出栈序列判定可能性是存在简便思路的。 对比分析题中 Sample 给出的序列,结合上面提到的两条冲突条件入手分析:

  • 1.栈中数据量不超过栈的容量:

    只有在入栈时,才会需要考虑栈中数据是否超量。出栈序列中的每个数,都以为着在出栈操作之前,它刚入栈, 那么当它入栈的时候能否判定是否超过栈容量呢?可以的,(当前的出栈数值 - 已经执行过的出栈操作数量)就是当前栈中元素的数量。

  • 2.出栈只能从栈顶取,不应该出现从固定的堆栈中取出其他数据的情况。

    根据观察分析发现,当某数据 m 出栈之后,比 m 小的数据如果在 m 之后出栈的,它们所组成的序列本身需要保持从大到小的顺序排列。 距离如3 2 1 7 5 6 4这个序列,在7之后有5 6 4这个子序列,它们都大于7,但却没有保持一个递减的顺序,不合法。

更多分析参见博文《出栈序列的可能性判定》

1052. Linked List Sorting (25)

题意

链表的节点被表示为{地址, 值, 下一个指针地址},其中如果NULL的地址表示为-1, 地址为5正数,值的范围为[-10^5, 10^5]。

给定N(< 10^5)个节点以及其头指针,要求按照每个节点上值的大小重新排序,并按照链表顺序输出每个节点。

分析

将链表中的节点按值做qsort()排序,然后调整每个值的next指针即可。需要注意的有:

  • 1.INPUT中的节点并不保证全是链表中的,先需要过滤掉悬空的节点。
  • 2.head直接指向-1(NULL)的情况需要特殊处理。

1053. Path of Equal Weight (30)

题意

给定一棵树,有N( <= 100) 个节点,每个节点有一个权重,另给定一个权重值S(< 230)。要求找到从根节点出发到叶节点的路径上,所有点权重值和等于S的所有情况,并按照逆字典序输出。

分析

使用邻接表的方式构建树,dfs搜索,由于需要逆字典序输出,处理前需要对每个节点的儿子节点邻接表进行排序,合理剪枝即可。

需要注意的是:结果路径要求以叶子节点结束。

1054. The Dominant Color (20)

题意

给定一个M(<= 800)*N(<=600)个像素点,每个像素点的范围为[0, 2^24],要求找出其中出现次数超过总数量的一半左右的点,称作restrict dominant color.

分析

由于条件比较特殊,使用一个计数器count,一个寄存器color就可以实现对超过一半数目的选项的挑选。过程如下:

  • 1.count初始化为0,color初始化为-1
  • 2.读入新的颜色值newColor,如果newColor跟寄存器的color一样,则计数器count加一。如果不一样,且count不为0,则count减一;如果不一样,且count为0,则寄存器中的color被置为newColor
  • 3.不断循环2,直到读入所有颜色值。这时候,寄存器color中存储的就是结果。

这个方法的巧妙之处,在于寄存器和计数器保存了状态,用抵消的思想,最终得到了较多数量的状态。思考时,不妨假设所有颜色值只有两个,一个是超过一半数量的restrict dominant color,另一个则是少于一半数量的颜色,经过累加和寄存的操作,少于一半的颜色肯定会被多余一般的颜色抵消掉,最后剩下多于一半的颜色。另外,大家不妨想一下,本题的最后,计数器中的值就是restrict dominant color超过其他颜色的数量么?

1055. The World's Richest (25)

题意

福布斯排行榜上,给出了N(<=10^5)个人的名单,每个名单包含了不超过8个字符的姓名,(0,200]的年龄以及[-10^6,10^6]的财富值。

另外,给出了K(<=10^3)次查询,以及每次查询要求的结果条数M(<=100)。每次查询给定一个年龄区间,要求查询出这个区间范围内财富排名前M的人的名单。如果财富值相同,按姓名字典序排列。

分析

这道题时间限制比较严格。有两种思路:

第1种思路:
  • 1.所有年龄做qsort()排序;
  • 2.分离到不同年轻的人的数组中,此时每个年龄中,都是排序好的。
  • 3.对于每个查询,从2中所得数组里进行归并排序,归并的每次比较过程,使用最大堆实现。
第2种思路:
  • 1.所有年龄做排序
  • 2.对排序好的年龄,每个年龄计数减掉100名之后的人。
  • 3.然后对待查询轮训过滤即可。

1056. Mice and Rice (25)

题意

分组淘汰赛背景。给出Np(<=1000)个参赛者,限定每场比赛最多有Ng(<=1000)个参赛者参加,如果一轮比赛中,组队的过程单出几个人,也将他们组成一次比赛。每场比赛决出一名胜者,参加到下一轮的淘汰赛中,而同一轮的负者都拥有相同的排名,如此循环往复,直到决出第一。

输入数据中还规定了必须依据顺序分组,而初始顺序体重已经给出。

分析

模拟题。用队列存储剩下的参赛队员,每轮比赛做一次循环,直到队列为空。处理一轮比赛时,负者的rank等于该轮比赛场次+1.换分组别的时候,需要仔细。

1057. Stack (30)

题意

在stack的基础上,增加了一个PeekMedian操作定义,要求输出stack中所有数据的中间大小的数。

题目给出N(<=10^5)个对stack的顺序操作,要求输出操作结果。其中保证每次操作的值不大于10^5。

分析

使用stl中的stack模拟常规栈操作,关键问题在于中位数的读取。由于时间限制比较严格,使用诸如优先队列等方式会超时。考虑到每次的操作数都不超过10^5,想到诸如使用hash的方式用空间换时间。但即使是开一个int hash[100001]的hash表,也只能记录读入的所有数据的次数,无法提供高效的查询操作。实际上,在hash方式的前提下,使用树状数组能很好的解决这个问题。 (另有一篇详细介绍树状数组的译文:请戳)

int hash[100001]建立树状数组,然后通过二分的方式,就可方便的查询到hash数组中那个坐标下的统计值处于中间位置,这个坐标的值也就是中位数了。

1058. A+B in Hogwarts (20)

题意

给定的数的结构如下:a.b.c,其中a的范围是[0, 10^7],b的范围是[0,17),c的范围是[0,29)。给定两个数,要求计算他们的和。

分析

简单模拟题,有一个坑:题目交代最高位的区间为[0, 100000000],但是没说如果两数相加超过这个值怎么办。需要将最高位的结果区间设定为20000000以上才AC。

1059. Prime Factors (25)

题意

给定一个正整数,要求格式化输出它的素因数相乘的形式。

分析

由于时间限制,不可以简单的重复判定素数。可以使用DP的思想做素数的判定。

1060. Are They Equal (25)

题意

科学计数法相关背景。假设机器只能存储3个有效数字,那么1230012358.9在机器侠都表达都为0.123*10^5,他们相等。其中有效数字使用简单截尾方式,不进位。

给定两个不大于10^100的非负整数,以及有效位数N(<=100),要求计算在对应的精确位数下,两数的表达是否相等。

分析

由于非负整数非常大,不可使用longlong甚至精确度不高的double,当做字符串来处理。

需要注意的一点是对值为0的情况的处理。比如0在有效位数为3下的表达为:0.00*10^0

你可能感兴趣的:(算法)