跳到主要内容

小美的排列询问

美团 2024 秋招笔试编程题

题目描述​

小美拿到了一个排列。她想知道在这个排列中,数字 x 和 y 是否是相邻的。 排列是指一个长度为 n 的数组,其中 1 到 n 每个元素恰好出现一次。

输入格式​

第一行一个正整数 n,代表排列的长度。 第二行 n 个正整数,代表排列的元素。 第三行两个正整数 x 和 y,用空格隔开。

输出格式​

如果 x 和 y 在排列中相邻,输出 Yes;否则输出 No。

示例​

示例 1​

输入:

4
1 4 2 3
2 4

输出:

Yes

说明: 排列为 1 4 2 3,4 在第 2 位、2 在第 3 位,下标相差 1,相邻。

示例 2​

输入:

5
3 4 5 1 2
3 2

输出:

No

说明: 3 在第 1 位、2 在第 5 位,下标相差 4,不相邻。


解题思路​

第一步:把「相邻」翻译成下标条件​

数组里「两个数相邻」只有一种含义:它们的位置下标相差 1。 所以问题变成:找出 x 和 y 各自出现的位置,判断下标差是否为 1。

第二步:暴力查找(不推荐)​

每次都从头扫一遍数组找 x 和 y,单次查询 O(n)。 因为题目只问一次,暴力也能过,但没有体现出「排列」这个条件的好处。

第三步:值 → 下标 的映射(推荐)​

排列的一个好处是每个值恰好出现一次,所以可以建一张表: 「值 → 在数组中的下标」。一次遍历把表建好,查询就是 O(1):

abs(pos[x] - pos[y]) == 1  →  Yes

Python 里用 dict,或者因为值域是 1..n,直接用长度为 n + 1 的数组更快。


完整代码实现​

算法可视化 · 逐帧回放这道题的代码18 帧 · 录制输入
import sys


def solve() -> None:
"""记录每个值的位置,判断下标是否相差 1"""
data = sys.stdin.read().split()
if not data:
return
n = int(data[0])
a = data[1:1 + n]
x = data[1 + n]
y = data[2 + n]

pos = {}
for i, v in enumerate(a):
pos[v] = i
sys.stdout.write("Yes\n" if abs(pos[x] - pos[y]) == 1 else "No\n")


if __name__ == "__main__":
solve()

示例推演​

以 n = 4, a = [1, 4, 2, 3], x = 2, y = 4 为例:

值下标
10
41
22
33

|pos[2] - pos[4]| = |2 - 1| = 1 → 输出 Yes。


复杂度分析​

解法时间复杂度空间复杂度说明
每次线性查找O(n)O(1)只问一次也能过
值 → 下标 映射O(n)O(n)推荐,查询 O(1)

易错点总结​

1. 把「相邻」理解成数值相邻​

题目说的是位置相邻,不是数值相差 1。 1 4 2 3 里 4 和 2 数值差 2,但位置相邻 → Yes。

2. 输出大小写​

题目要求输出 Yes / No(首字母大写),不是 YES / NO。

3. 忘记 x 或 y 可能在末尾​

用「值 → 下标」的映射就不会有边界问题; 如果用双指针找相邻对,要注意数组末尾。


扩展思考​

  • 若问的是「x 和 y 之间隔了几个数」,答案就是 |i - j| - 1。
  • 排列的「值恰好出现一次」性质在环(首尾相邻)问题里要单独处理。

相关题目​

自测​

加载评论中...