public void UnionTest2() { var dsu = new DSU <int>(); dsu.MakeSet(1); dsu.MakeSet(2); dsu.MakeSet(3); dsu.MakeSet(4); dsu.MakeSet(5); Assert.AreEqual(4, dsu.Find(4)); dsu.Unite(1, 4, isRandom: false); dsu.Unite(3, 5, isRandom: false); Assert.AreEqual(1, dsu.Find(4)); Assert.AreEqual(1, dsu.Find(1)); Assert.AreEqual(2, dsu.Find(2)); Assert.AreEqual(3, dsu.Find(5)); Assert.AreEqual(3, dsu.Find(3)); dsu.Unite(5, 2, isRandom: false); Assert.AreEqual(3, dsu.Find(5)); Assert.AreEqual(3, dsu.Find(3)); Assert.AreEqual(3, dsu.Find(2)); }
public void UnionTest() { var dsu = new DSU <int>(); dsu.MakeSet(1); dsu.MakeSet(2); dsu.Unite(1, 2, isRandom: false); Assert.That(dsu.Find(1), Is.EqualTo(dsu.Find(2))); }
/// <summary> /// Nov. 19, 2020 /// Union find algorithm /// study code /// https://leetcode.com/problems/sentence-similarity-ii/solution/ /// Time complexity: /// Time Complexity: O(N log P + P), where N is the maximum length of words1 and words2, /// and P is the length of pairs. If we used union-by-rank, this complexity improves to /// O(N * a(P) + P), close to O(N + P), where α is the Inverse-Ackermann function. /// </summary> /// <param name="words1"></param> /// <param name="words2"></param> /// <param name="pairs"></param> /// <returns></returns> public bool AreSentencesSimilarTwo(string[] words1, string[] words2, IList <IList <string> > pairs) { var length1 = words1.Length; var length2 = words2.Length; var pLength = pairs.Count; if (length1 != length2) { return(false); } // index -> indexMap better name? var indexMap = new Dictionary <string, int>(); int count = 0; var dsu = new DSU(2 * pLength); foreach (var pair in pairs) { // go through two words in one pair foreach (var p in pair) { if (!indexMap.ContainsKey(p)) { indexMap.Add(p, count++); } } dsu.Union(indexMap[pair[0]], indexMap[pair[1]]); } for (int i = 0; i < length1; ++i) { var w1 = words1[i]; var w2 = words2[i]; if (w1.CompareTo(w2) == 0) { continue; } if (!indexMap.ContainsKey(w1) || !indexMap.ContainsKey(w2) || dsu.Find(indexMap[w1]) != dsu.Find(indexMap[w2])) { return(false); } } return(true); }
public int RemoveStones(int[][] stones) { var dsu = new DSU(20000); foreach (var stone in stones) { dsu.Union(stone[0], stone[1] + 10000); } var seen = new HashSet <int>(); foreach (var stone in stones) { seen.Add(dsu.Find(stone[0])); } return(stones.Length - seen.Count); }
public IList <IList <string> > AccountsMerge(IList <IList <string> > accounts) { EmailToId = new Dictionary <string, int>(); EmailToName = new Dictionary <string, string>(); foreach (var account in accounts) { if (account.Count < 2) { continue; } var name = account[0]; for (var i = 1; i < account.Count; i++) { if (!EmailToId.ContainsKey(account[i])) { var id = EmailToId.Count; EmailToId[account[i]] = id; EmailToName[account[i]] = name; } } } var totalAccounts = EmailToId.Count; DSU = new DSU(totalAccounts); foreach (var account in accounts) { // var name = account[0]; for (var i = 1; i < account.Count - 1; i++) { var id1 = EmailToId[account[i]]; var id2 = EmailToId[account[i + 1]]; if (id1 != id2) { DSU.Union(id1, id2); } } } var result = new Dictionary <int, List <string> >(); foreach (var email in EmailToName.Keys) { int index = DSU.Find(EmailToId[email]); if (result.TryGetValue(index, out var list)) { list.Add(email); } else { result[index] = new List <string> { email }; } } foreach (var emails in result.Values) { emails.Sort((x, y) => { var i = 0; while (i < x.Length && i < y.Length) { if (x[i] != y[i]) { return(x[i].CompareTo(y[i])); } i++; } return(x.Length.CompareTo(y.Length)); }); emails.Insert(0, EmailToName[emails[0]]); } return(result.Values.ToList <IList <string> >()); }