python交换字符串里的元素_1202交换字符串中的元素(和查找集),并,查集

1. 问题描述:

给你一个字符串 s,以及该字符串中的一些「索引对」数组 pairs,其中 pairs[i] = [a, b] 表示字符串中的两个索引(编号从 0 开始)。你可以 任意多次交换 在 pairs 中任意一对索引处的字符。返回在经过若干次交换后,s 可以变成的按字典序最小的字符串。

示例 1:

输入:s = "dcab", pairs = [[0,3],[1,2]]

输出:"bacd"

解释:

交换 s[0] 和 s[3], s = "bcad"

交换 s[1] 和 s[2], s = "bacd"

示例 2:

输出:"abcd"

解释:

交换 s[0] 和 s[3], s = "bcad"

交换 s[0] 和 s[2], s = "acbd"

交换 s[1] 和 s[2], s = "abcd"

示例 3:

输入:s = "cba", pairs = [[0,1],[1,2]]

输出:"abc"

解释:

交换 s[0] 和 s[1], s = "bca"

交换 s[1] 和 s[2], s = "bac"

交换 s[0] 和 s[1], s = "abc"

提示:

1 <= s.length <= 10^5

0 <= pairs.length <= 10^5

0 <= pairs[i][0], pairs[i][1]

s 中只含有小写英文字母

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/smallest-string-with-swaps

2. 思路分析:

① 一开始的时候发现题目真的挺难,没有啥思路,所以放弃自己思考,看一下评论区的题解,发现大部分使用的是并查集来解决的,假如能够互通连接在一起的节点,我们是可以先确定某些一个或者某些字母将其放在对应的位置,这样这些字母后面是不需要移动的了,然后通过交换剩余可以改变位置的字母最终得到字典序最小的字母序列,简单来说就是将连在一起的节点中的字母进行排序,这样得到的肯定是字典序最小的序列,因为我是可以通过若干次的移动确定所有字母的位置并且将其放在对应的位置上的,其实这也就是并查集的问题

② 我们在一开始的时候初始化每一个节点的父节点,在遍历的时候修改当前节点的父节点,另外声明一个字典用来添加连在一起的节点,这样我们就可以对连在一起的节点范围内的字母进行排序组成字典序更小的序列,这个思路还是蛮好理解的

③ 其中会使用到collections.defaultdict(list)函数用来创建一直接可以使用键访问的字典,并且使用zip函数可以将下标与对应字母的列表一一进行对应这样就可以添加到结果集中了,下面的代码是领扣评论区中的代码:

https://leetcode-cn.com/problems/smallest-string-with-swaps/solution/bing-cha-ji-python-by-fa-kuang-de-jie-zi/

,在python学习的过程中可以多看看别人写的代码可以多学习一下各种各种常见的函数,对于自己的熟悉各种函数的方法也是非常有好处的(感觉刷题思考看别人写的代码是一个很快学习常见函数用法的方法)

3. 代码如下:

import collections

class Solution:

def smallestStringWithSwaps(self, s: str, pairs: [int]) -> str:

# 字典: 初始化每一个节点的父节点

p = {i: i for i in range(len(s))}

# 递归: 在查询x节点的时候修改x的父节点

def f(x):

if x != p[x]:

p[x] = f(p[x])

return p[x]

# 在遍历的时候修改节点的父节点

for i, j in pairs:

p[f(j)] = f(i)

# 合并可交换位置

# 使用字典将所有在同一个父节点的节点联系起来

d = collections.defaultdict(list)

# 使用map函数迭代调用f函数, 传入方法中的是字典中的键

for i, j in enumerate(map(f, p)):

d[j].append(i)

# 排序

ans = list(s)

for q in d.values():

# 注意返回的是列表

t = sorted(ans[i] for i in q)

# zip函数返回一个元祖

for i, c in zip(sorted(q), t):

ans[i] = c

return ''.join(ans)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值