LeetCode LCR 117. 相似字符串组

题目描述

LCR 117. 相似字符串组

思路分析

解法一:并查集(推荐)

核心思路

  • 将每个字符串视作一个节点,若两字符串相似则连接。
  • 相似判断:不同字符位置数为 0 或 2(题目保证同字母集合)。
  • 最终连通分量数量即为相似字符串组数。

复杂度分析

  • 时间复杂度:O(n^2 * L),其中 n 为字符串数量,L 为字符串长度。
  • 空间复杂度:O(n),并查集数组。
class Solution {
    public int numSimilarGroups(String[] strs) {
        int n = strs.length;
        UnionFind uf = new UnionFind(n);

        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (isSimilar(strs[i], strs[j])) {
                    uf.union(i, j);
                }
            }
        }

        return uf.count();
    }

    private boolean isSimilar(String a, String b) {
        int diff = 0;
        for (int i = 0; i < a.length(); i++) {
            if (a.charAt(i) != b.charAt(i)) {
                diff++;
                if (diff > 2) {
                    return false;
                }
            }
        }
        return diff == 0 || diff == 2;
    }

    private static class UnionFind {
        private final int[] parent;
        private int count;

        UnionFind(int n) {
            parent = new int[n];
            count = n;
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }
        }

        int find(int x) {
            if (parent[x] != x) {
                parent[x] = find(parent[x]);
            }
            return parent[x];
        }

        void union(int a, int b) {
            int ra = find(a);
            int rb = find(b);
            if (ra == rb) {
                return;
            }
            parent[ra] = rb;
            count--;
        }

        int count() {
            return count;
        }
    }
}
func numSimilarGroups(strs []string) int {
    n := len(strs)
    uf := newUnionFind(n)

    for i := 0; i < n; i++ {
        for j := i + 1; j < n; j++ {
            if isSimilar(strs[i], strs[j]) {
                uf.union(i, j)
            }
        }
    }

    return uf.count
}

func isSimilar(a, b string) bool {
    diff := 0
    for i := 0; i < len(a); i++ {
        if a[i] != b[i] {
            diff++
            if diff > 2 {
                return false
            }
        }
    }
    return diff == 0 || diff == 2
}

type UnionFind struct {
    parent []int
    count  int
}

func newUnionFind(n int) *UnionFind {
    parent := make([]int, n)
    for i := 0; i < n; i++ {
        parent[i] = i
    }
    return &UnionFind{parent: parent, count: n}
}

func (u *UnionFind) find(x int) int {
    if u.parent[x] != x {
        u.parent[x] = u.find(u.parent[x])
    }
    return u.parent[x]
}

func (u *UnionFind) union(a, b int) {
    ra := u.find(a)
    rb := u.find(b)
    if ra == rb {
        return
    }
    u.parent[ra] = rb
    u.count--
}

相似题目

题目 难度 考察点
684. 冗余连接 中等 并查集
947. 移除最多的同行或同列石头 中等 并查集
1202. 交换字符串中的元素 中等 并查集
721. 账户合并 中等 并查集
1319. 连通网络的操作次数 中等 并查集
本文作者:
本文链接: https://hgnulb.github.io/blog/2026/11359213
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!