Leetcode刷题笔记 1202. 交换字符串中的元素

1202. 交换字符串中的元素

时间:2021年1月11日
知识点:图、并查集
题目链接

题目
给你一个字符串 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
输入:s = “dcab”, pairs = [[0,3],[1,2],[0,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.length
  • s 中只含有小写英文字母

解法

  1. 这是一道并查集的题
  2. 通过对pairs的分析 把他想象成边 每个字符看作节点 我们可以知道如果哪些字符是连通的
  3. 如果几个字符是连通的 那么他们可以随意交换位置 可以得出最小的字符
  4. 对于多个连通 以祖先节点为key 所有连通的成为vector 每个排好序
  5. 然后放入答案数组 这里是重点 可能不太好想 用并查集的find找到对应的连通 返回一个字符即可

代码

//头文件
#include "cheader.h"
class Solution {
public:
    struct UN{
        vector<int> ancestor;
        UN(int x){
            ancestor.resize(x);
            for(int i = 0;i < x;i++)
                ancestor[i] = i;
        }
        int find(int x){
            if(ancestor[x] == x)
                return x;
            else
                return  ancestor[x] = find(ancestor[x]);
        }
        void merge(int a, int b){
            ancestor[find(a)] = find(b);
        }
    };
    string smallestStringWithSwaps(string s, vector<vector<int>>& pairs) {
        int n = s.size();
        UN un = UN(n);
        for(vector<int> x: pairs){
            un.merge(x[0], x[1]);
        }
        unordered_map<int, vector<char>> mp;
        // 在同一个连通图中的放在一起
        for(int i = 0; i < n; i++)
            mp[un.find(i)].push_back(s[i]);
        //遍历每个连通 同一个连通中的字符 从大到小排序
        for(auto& [x,ch]: mp)
            sort(ch.begin(),ch.end(),greater<char>());
        string ans;
        // 找到每个字符(这里用下标建立的并查集)所对应的连通 取出连通中最小的字符
        for(int i = 0; i < n; i++){
            int x = un.find(i);
            ans += mp[x].back();
            mp[x].pop_back();
        }
        return ans;
    }
};
int main()
{
    Solution S;
    string s = "dcab";
    vector<vector<int>> pairs;
    pairs.push_back(vector<int> {0,3});
    pairs.push_back(vector<int> {1,2});
    pairs.push_back(vector<int> {0,2});
    cout<<S.smallestStringWithSwaps(s, pairs);
    return 0;
}

今天也是爱zz的一天哦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值