Java 实现并查集查询、合并

前言

【题目描述】
给定一个没有重复值的整型数组 arr,初始时认为 arr 中每一个数各自都是一个单独的集合。
请设计一种叫 UnionFind 的结构,并提供以下两个操作。
1)boolean isSameSet(int a, int b):查询 a 和 b 这两个数是否属于一个集合。
2)void union(int a, int b):把 a 所在的集合与 b 所在的集合合并在一起,原本两个集合各自的元素以后都算作同一个集合。

【要求】
如果调用 isSameSet 和 union 的总次数逼近或超过 O(N),请做到单次调用 isSameSet 或 union
方法的平均时间复杂度为 O(1)。

思路

  1. 一开始每个元素自己形成单独的集合,同时其父结点指向自己【这里父结点为当前集合的根结点】;
    自成集合
  2. 定义查找集合根结点的方法,依次查找father结点,查找过程中将路过的所有结点都直接挂到根结点上,压缩查询路径,降低查询时间复杂度;

查询集合根结点

  1. 判断两个元素是否处于同一集合,即查询两个元素对应集合的根结点是否一致即可;
  2. 合并两个集合遵守如下原则:
    a.如果两个集合根结点一致,则说明属于同一个集合,无须进行合并操作;
    b.如果两个集合根结点不一致,则需要进行合并操作,将集合个数少的集合合并到集合个数多的集合【本质目的还是降低查找集合根结点层级,如下图查找结点2,如果以集合少的4为根结点,则查找层级+1】,如下图:
    合并集合

代码实现

  • 定义结点类Node;
    private static class Node<V> {
        private V value;

        public Node(V value) {
            this.value = value;
        }
    }

  • 实现并查集类UnionFindSet;
 public static class UnionFindSet<V> {
        /**
         * V -> Node 关系映射
         */
        private HashMap<V, Node<V>> elementMap;
        /**
         * 存储Node以及其集合根结点
         */
        private HashMap<Node<V>, Node<V>> fatherMap;
        /**
         * 存储集合根结点元素 以及其集合元素数量
         */
        private HashMap<Node<V>, Integer> sizeMap;

        public UnionFindSet(List<V> list) {
            elementMap = new HashMap<>();
            fatherMap = new HashMap<>();
            sizeMap = new HashMap<>();
            makeSet(list);
        }

        private void makeSet(List<V> list) {
            for (V v : list) {
                Node node = new Node(v);
                elementMap.put(v, node);
                fatherMap.put(node, node);
                sizeMap.put(node, 1);
            }
        }

        /**
         * 递归查找一个Node对应的头结点
         *
         * @return
         */
        private Node findHead(Node node) {
            if (node == null) {
                return null;
            }
            Node father = fatherMap.get(node);
            if (father != node) {
                father = findHead(father);
            }
            //将当前结点直接挂接到头结点上,降低层级
            fatherMap.put(node, father);
            return father;
        }

        /**
         * 查找两个结点是否处于同一集合
         *
         * @param a 结点a
         * @param b 结点b
         * @return
         */
        public boolean isSameSet(V a, V b) {
            if (elementMap.containsKey(a) && elementMap.containsKey(b)) {
                return findHead(elementMap.get(a)) == findHead(elementMap.get(b));
            }
            return false;
        }

        /**
         * 合并两个集合
         *
         * @param a
         * @param b
         */
        public void union(V a, V b) {
            if (elementMap.containsKey(a) && elementMap.containsKey(b)) {
                Node aHead = findHead(elementMap.get(a));
                Node bHead = findHead(elementMap.get(b));
                //两者头结点相同,不需要合并
                if (aHead == bHead) {
                    return;
                }
                int aSize = sizeMap.get(aHead);
                int bSize = sizeMap.get(bHead);
                //将结点数少的挂在结点数多的上面
                if (aSize <= bSize) {
                    fatherMap.put(aHead, bHead);
                    sizeMap.put(bHead, aSize + bSize);
                } else {
                    fatherMap.put(bHead, aHead);
                    sizeMap.put(aHead, aSize + bSize);
                }
            }

        }

    }

测试用例

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4};
        List<Integer> list = new ArrayList<>();
        for (int i : arr) {
            list.add(i);
        }
        UnionFindSet set = new UnionFindSet(list);
        set.union(1, 3);
        set.union(2, 4);

        boolean sameSet1 = set.isSameSet(2, 3);
        boolean sameSet2 = set.isSameSet(2, 4);
        System.out.println(sameSet1);
        System.out.println(sameSet2);

    }
输出结果
false
true

结语

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用Apache POI库来将结果集合并到Excel。以下是一个示例代码,可以将查询结果集动态添加到Excel: ```java import java.io.FileOutputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.usermodel.HSSFPalette; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.IndexedColors; public class ExcelGenerator { public static void main(String[] args) throws Exception { //Connect to database Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "myuser", "mypassword"); Statement stmt = conn.createStatement(); //Execute query String query = "SELECT * FROM mytable"; ResultSet rs = stmt.executeQuery(query); //Create workbook and sheet HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet("Result Set"); //Create header row HSSFRow header = sheet.createRow(0); for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { HSSFCell cell = header.createCell(i - 1); cell.setCellValue(rs.getMetaData().getColumnName(i)); HSSFCellStyle style = workbook.createCellStyle(); HSSFFont font = workbook.createFont(); font.setBold(true); style.setFont(font); style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); style.setFillPattern(CellStyle.SOLID_FOREGROUND); cell.setCellStyle(style); } //Create data rows int rowCount = 1; while (rs.next()) { HSSFRow row = sheet.createRow(rowCount++); for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { HSSFCell cell = row.createCell(i - 1); cell.setCellValue(rs.getString(i)); } } //Auto-size columns for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) { sheet.autoSizeColumn(i); } //Save workbook to file FileOutputStream fos = new FileOutputStream("resultset.xls"); workbook.write(fos); fos.close(); //Close connections rs.close(); stmt.close(); conn.close(); } } ``` 这个示例代码将查询结果集动态添加到Excel,并使用Apache POI库进行格式化和保存。您可以根据自己的需求进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值