set 集合

题目考点

这道题主要考的是这几个知识点:

  1. set 集合
  2. 集合的几种原地修改操作
    • intersection_update()
    • update()
    • symmetric_difference_update()
    • difference_update()
  3. 输入处理
  4. 循环读取多组操作
  5. 最后对集合元素求和 sum()

这道题本质上不是在考复杂算法,而是在考你能不能:

  • 把输入一组一组读出来
  • 看懂“操作名 + 另一个集合”
  • 对原集合 A 进行对应修改

所以核心不是“算”,而是“按要求改集合”。


审题

输入是什么

题目会给你:

  1. 第一行:集合 A 的元素个数
  2. 第二行:集合 A 的所有元素
  3. 第三行:整数 N,表示接下来有几次操作
  4. 接下来每次操作占两行:
    • 第一行:操作名 和 另一个集合的长度
    • 第二行:另一个集合的元素

输出是什么

输出经过这 N 次操作之后,集合 A 中所有元素的和。

题目要求我们做什么

题目不是让你新建很多结果,而是让你不断修改原来的集合 A

也就是说:

  • 先有一个初始集合 A
  • 然后对它执行若干次集合操作
  • 最后输出 sum(A)

容易忽略的点

1. 每次操作都会直接修改 A

比如:

A.intersection_update(B)

这不是返回一个新集合,而是直接把 A 改掉。

2. 每次操作第一行里的“长度”通常不用手动参与计算

例如:

intersection_update 10

这里的 10 只是告诉你下一行有 10 个数。
实际写程序时,我们通常直接把下一行读成一个集合就行,不一定非要用这个 10

3. 集合是无序的

所以不要想着按位置去处理,集合题的重点是“有没有这个元素”。


思路提示

先不要急着写代码,先把题目流程想清楚。

第一步:读入初始集合 A

题目先给出 A 的元素个数,再给出元素列表。
我们把第二行转成集合即可。

第二步:读入操作次数 N

说明接下来要循环 N 次,每次都要处理一组“操作”。

第三步:每次操作分两部分读

先读操作名,比如:

  • intersection_update
  • update
  • symmetric_difference_update
  • difference_update

再读下一行,把它变成另一个集合 B

第四步:根据操作名,修改 A

看到什么操作名,就调用对应的方法。

第五步:全部做完后,输出 sum(A)


完整设计思路

这道题最好的做法,是把它理解成“按命令执行”。

第 1 步:建立集合 A

比如输入这一行:

1 2 3 4 5

我们可以写:

A = set(map(int, input().split()))

这样就把这一行整数转成集合了。

注意前面那一行元素个数:

int(input())

这一行通常只是题目格式要求,很多时候读了但不一定非要使用。


第 2 步:读取操作次数 N

N = int(input())

表示后面要做 N 次集合变换。


第 3 步:每次先读“操作名”

例如这一行:

intersection_update 10

可以这样拆开:

operation, _ = input().split()

这里为什么第二个用 _

因为这一行有两个东西:

  • operation:操作名
  • 10:另一个集合的长度

但这个长度对我们后面处理并不是必须的,所以常用 _ 表示“读进来了,但暂时不用”。


第 4 步:读取另一个集合

下一行就是这个操作要用到的集合,比如:

2 3 5 6 8 9 1 4 7 11

可以写成:

B = set(map(int, input().split()))

第 5 步:根据操作名执行对应方法

这是整道题最关键的部分。

情况 1:交集更新

A.intersection_update(B)

意思是:A 只保留和 B 都有的元素。


情况 2:并集更新

A.update(B)

意思是:把 B 的元素加入到 A 中。


情况 3:对称差更新

A.symmetric_difference_update(B)

意思是:保留“只在其中一个集合里出现”的元素。

也可以理解成:

  • 两边都有的删掉
  • 只在一边有的保留

情况 4:差集更新

A.difference_update(B)

意思是:从 A 里删掉那些也在 B 中的元素。


第 6 步:最后求和

所有操作结束后:

print(sum(A))

代码实现

下面给你一个适合初学者、结构很清楚的版本。

# 读入集合 A 的元素个数(这题里主要是配合输入格式,后面不一定要用)
n = int(input())

# 读入集合 A
A = set(map(int, input().split()))

# 操作次数
N = int(input())

for _ in range(N):
    # 读入操作名和另一个集合的长度
    operation, length = input().split()

    # 读入另一个集合
    B = set(map(int, input().split()))

    # 根据操作名执行对应操作
    if operation == "intersection_update":
        A.intersection_update(B)
    elif operation == "update":
        A.update(B)
    elif operation == "symmetric_difference_update":
        A.symmetric_difference_update(B)
    elif operation == "difference_update":
        A.difference_update(B)

# 输出最终集合元素之和
print(sum(A))

运行演示

我们就用题目里的样例来手动走一遍。

初始集合

A = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 24, 52}

第一次操作

intersection_update
B = {2, 3, 5, 6, 8, 9, 1, 4, 7, 11}

交集更新后,A 只保留共同元素:

A = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11}

第二次操作

update
B = {55, 66}

B 加入 A

A = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 55, 66}

第三次操作

symmetric_difference_update
B = {22, 7, 35, 62, 58}

对称差更新规则是:

  • 两边都有的删掉
  • 只在一边有的保留

因为 7 在两边都有,所以删掉。
22, 35, 62, 58 原来不在 A 中,所以加进去。

结果:

A = {1, 2, 3, 4, 5, 6, 8, 9, 11, 22, 35, 55, 58, 62, 66}

第四次操作

difference_update
B = {11, 22, 35, 55, 58, 62, 66}

A 中删掉这些元素:

A = {1, 2, 3, 4, 5, 6, 8, 9}

最后求和

1 + 2 + 3 + 4 + 5 + 6 + 8 + 9 = 38

所以输出:

38

方法总结

以后遇到这种题,你可以按这个模板去识别。

看到这些关键词,就要想到集合题

  • set
  • update
  • intersection
  • difference
  • symmetric_difference

做题步骤固定为

1. 先把原集合读出来

A = set(map(int, input().split()))

2. 再循环读命令

每次命令一般分两行:

  • 第一行:操作名
  • 第二行:另一个集合

3. 用 if/elif 分发操作

这一步本质就是“命令匹配”。

4. 最后按题目要求输出

这题是:

print(sum(A))

易错点提醒

易错点 1:把集合写成列表

这题必须用 set,因为操作本来就是集合操作。
如果你用 list,会非常麻烦,而且不符合题目本意。


易错点 2:忘了把输入转成整数

如果你写成:

set(input().split())

得到的是字符串集合,不是整数集合。

要写成:

set(map(int, input().split()))

易错点 3:把方法名字写错

比如:

  • intersection_update
  • symmetric_difference_update
  • difference_update

这些名字都比较长,拼写容易错。


易错点 4:误以为这些方法有返回值

这些方法是“原地修改”,不要写成:

A = A.update(B)

因为这样很容易出问题。
正确写法就是直接:

A.update(B)

补充说明:为什么第一行的元素个数经常没用上

题目第一行给你:

16

第二行给你:

1 2 3 4 ...

从严谨上说,第一行是在告诉你第二行应该有多少个数。
但在 Python 里,我们通常直接把第二行整行读入再拆分:

A = set(map(int, input().split()))

所以很多时候这个数量只是“输入格式说明”,程序里不一定非要用它控制读取。

这在很多刷题题目里都很常见。


练习

下面给你一道同类型的小练习,先自己试着做。

题目

已知:

A = {1, 2, 3, 4, 5}

依次执行下面三步操作:

  1. update({6, 7})
  2. difference_update({2, 4, 6})
  3. symmetric_difference_update({1, 3, 8})

问最后集合 A 的元素之和是多少?

提示

你可以按这三步手动模拟:

  1. 先把新元素加进去
  2. 再删掉指定元素
  3. 最后做对称差:共同的删掉,只出现一次的保留

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇