1202. Smallest String With Swaps

11 篇文章 0 订阅
1 篇文章 0 订阅
  • 问题描述

LeetCode的第1202道题目,题目如下:

You are given a string s, and an array of pairs of indices in the string pairs where pairs[i] = [a, b] indicates 2 indices(0-indexed) of the string.

You can swap the characters at any pair of indices in the given pairs any number of times.

Return the lexicographically smallest string that s can be changed to after using the swaps.

  • 解决方案

这道题的本质在于根据可以交换的元素,可以组成若干个类似朋友圈的结构,朋友圈内部的元素可以互相交换,即可以按照从小到大的顺序进行排列,而朋友圈之间的元素不能交换。因此,首先用并查集结构找到有多少个“朋友圈”,每个“朋友圈”内部的所有字符用优先队列来存储,然后依次取出,即可完成“朋友圈”内部字符的排列。

代码如下:

public class SmallestStringWithSwaps {

    public static void main(String[] args){
        String s = "dcab";
        List<Integer> list = new ArrayList<>();
        list.add(0);
        list.add(3);
        List<List<Integer>> pairs = new ArrayList<>();
        pairs.add(list);
        list = new ArrayList<>();
        list.add(1);
        list.add(2);
        pairs.add(list);
        System.out.println(smallestStringWithSwaps( s,  pairs));
    }

    public static String smallestStringWithSwaps(String s, List<List<Integer>> pairs) {
        UnionFindSet union = new UnionFindSet(s.length());
        for(List<Integer> list : pairs){
            int a = list.get(0);
            int b = list.get(1);
            union.union(a,b);
        }
        char[] arr = s.toCharArray();
        HashMap<Integer, PriorityQueue<Character>> map = new HashMap<>();
        for(int i = 0;i < arr.length;i ++){
            int key = union.findRoot(i);
                if(map.containsKey(key)){
                    PriorityQueue<Character> q = map.get(key);
                    q.add(arr[i]);
                }
                else{
                    PriorityQueue<Character> q = new PriorityQueue<>();
                    q.add(arr[i]);
                    map.put(key,q);
                }
        }

        for(int i = 0;i < arr.length;i ++){
            int key = union.findRoot(i);
            if(key != -1){
                arr[i] = map.get(key).poll();
            }
        }
        return new String(arr);

    }
}

class UnionFindSet {
    private int[] elements;
    private int[] heights;
    public UnionFindSet(int n){
        elements = new int[n];
        heights = new int[n];
        Arrays.fill(elements,-1);
        Arrays.fill(heights,1);
    }

    public int findRoot(int i){
        while(elements[i] != -1){
            i = elements[i];
        }
        return i;
    }

    public void union(int x,int y){
        int xRoot = findRoot(x);
        int yRoot = findRoot(y);
        if(xRoot != yRoot){
            if(heights[xRoot] > heights[yRoot])
                elements[yRoot] = xRoot;
            else if(heights[xRoot] < heights[yRoot])
                elements[xRoot] = yRoot;
            else{
                elements[xRoot] = yRoot;
                heights[yRoot]++;
            }
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值