并查集+字符排序-困兽之斗(乐视题)

解决一个宝石字符串排序问题,通过彩虹连接的宝石可以交换位置,目标是最小化宝石序列的字典序。利用并查集思想,将可以连成交换链的位置设置相同的标志,找到相同标志的位置进行排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

士兵对小贱君说:“看到漂浮在你身边的宝石了吗?彩虹连接的两颗宝石可以任意交换位置,你需要通过一系列交换后使得宝石组成的字符串的字典序最小。若不能破阵,那还是请回吧!”
小贱君观察了一下周围的宝石,只见每颗宝石上标有一个小写字母,而且有一些宝石上通过彩虹与其他宝石相连。
琢磨了半天,他终于搞懂了这个阵法的意思:
若宝石系列为:dcba
其中有两道彩虹,分别是(0,1),(1,2),代表第一个位置上的宝石可以和第二个位置上的宝石互换,第二个位置上的宝石可以和第三个位置上的宝石互换,最终可以得到字典序最小的宝石系列:bcda。
作为小贱君的死党,你有什么方法帮助他破阵吗?

输入描述:

输入包含多组测试数据。 对于每组测试数据: 字符串s --- 代表宝石序列 n --- 代表有n条彩虹 接下来n行,每行两个数ai,bi --- 表示ai和bi由一条彩虹相连。 保证: 1<=s的长度<=10000 1<=n<=10000 且输入数据均合法。



输出描述:

对于每组数据,输出一个字符串


输入例子:
dcba
2
0 1
1 2
hellonowcoder
4
0 1
1 4
2 5
2 3

输出例子:
bcda
ehllonowcoder


/**
 * 将可以连成交换链的位置设置同一个整数标志,运用到并查集
 * 找到同一个整数标志的位置,对所有值进行排序,重新填入
 */
import java.util.*;
public class Main{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {

            char[] str = in.nextLine().toCharArray();
            int caihongN = Integer.parseInt(in.nextLine()), n = str.length;
            int[] caihong = new int[n];
            
            //设置同一串交换链的相同标志
            int mark=0;
            for(int i=0;i<caihongN;i++){
                String[] temp = in.nextLine().split(" ");
                int x = Integer.parseInt(temp[0]), y = Integer.parseInt(temp[1]);

                if(caihong[x]!=0 && caihong[y]!=0){
                    if(caihong[x] == caihong[y]) continue;
                    ///并查集合并步骤,将整数标志较大的交换链移到较小的标志下
                    int less = Math.min(caihong[x],caihong[y]), more = Math.max(caihong[x],caihong[y]);
                    for(int j=0;j<n;j++){
                        if(caihong[j] == more) caihong[j]=less;
                    }
                }
                else if(caihong[x]!=0) caihong[y]=caihong[x];
                else if(caihong[y]!=0) caihong[x] = caihong[y];
                else caihong[x] = caihong[y] = ++mark;
            }

            //取出可连成交换链的宝石位置,排序并重新放入
            while(mark>0){
                ArrayList<Integer> indexList = new ArrayList<Integer>();
                ArrayList<Character> charList = new ArrayList<Character>();

                for(int i=0;i<n;i++)
                    if(caihong[i]==mark) indexList.add(i);
                mark--;
                if(indexList.isEmpty()) continue;

                for(int i=0;i<indexList.size();i++) charList.add(str[indexList.get(i)]);
                Collections.sort(charList);
                for(int i=0, j=0;i<indexList.size();i++) str[indexList.get(i)] = charList.get(j++);
            }
            System.out.println(str);
        }
    }


}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值