学习记录

LeeCodeJava并查集

839.相似字符串组

思路:

使用双重循环遍历字符串组,将相似的字符串加入并查集,最后遍历查找根点的个数,即为结果.

我的代码:

  1. class Solution {
  2. public int numSimilarGroups(String[] strs) {
  3. UnionFind unionFind=new UnionFind(strs.length);
  4. for (int i = 0; i < strs.length; i++) {
  5. for (int j = i; j < strs.length; j++) {
  6. if(similar(strs[i],strs[j])){
  7. unionFind.union(i,j);
  8. }
  9. }
  10. }
  11. int count=0;
  12. for (int i = 0; i < unionFind.parents.length; i++) {
  13. if(unionFind.parents[i]==i){
  14. count++;
  15. }
  16. }
  17. return count;
  18. }
  19. //这个方法极其巧妙.
  20. public boolean similar(String a,String b){
  21. int count=0;
  22. for (int i = 0; i < a.length(); i++) {
  23. if(a.charAt(i)!=b.charAt(i)){
  24. count++;
  25. }
  26. if(count==3){
  27. return false;
  28. }
  29. }
  30. return count != 1;
  31. }
  32. }
  33. class UnionFind{
  34. int[] parents;
  35. int[] sizes;
  36. int n;
  37. public UnionFind(int n) {
  38. this.n = n;
  39. parents=new int[n];
  40. sizes=new int[n];
  41. Arrays.fill(sizes,1);
  42. for (int i = 0; i < parents.length; i++) {
  43. parents[i]=i;
  44. }
  45. }
  46. public boolean union(int a,int b){
  47. a=findParent(a);
  48. b=findParent(b);
  49. if(a==b){return false;}
  50. //a短,b长
  51. if(sizes[a]>sizes[b]){
  52. int temp=a;
  53. a=b;
  54. b=temp;
  55. }
  56. parents[a]=b;
  57. sizes[b]+=sizes[a];
  58. return true;
  59. }
  60. public int findParent(int a){
  61. if(parents[a]==a){
  62. return a;
  63. }else {
  64. return findParent(parents[a]);
  65. }
  66. }
  67. public boolean connected(int a,int b){
  68. return findParent(a)==findParent(b);
  69. }
  70. }

结论:

AC,这个已经是最高的并查集速度了.值得注意的是利用判断同一位置不同值的出现次数的方法来判断是否是只易位了一个字符,相当巧妙.值得单独为其增添一个代码块.

判断字符串只易位了一个字母:

  1. public boolean similar(String a,String b){
  2. int count=0;
  3. for (int i = 0; i < a.length(); i++) {
  4. if(a.charAt(i)!=b.charAt(i)){
  5. count++;
  6. }
  7. if(count==3){
  8. return false;
  9. }
  10. }
  11. return count != 1;
  12. }